TypeScript抽象类私有字段#recordNumber子类继承报错问题排查
解决TypeScript抽象类私有字段子类报错问题
我定义了一个抽象类AbstractRecord,用来统一所有记录类型的recordNumber字段(创建时该字段为null,后续可设为字符串),代码如下:
export abstract class AbstractRecord { #recordNumber: null | string; protected constructor() { this.#recordNumber = null; } get recordNumber(): null | string { return this.#recordNumber; } set recordNumber(arg: null | string) { this.#recordNumber = arg; } }
但当子类UserRecord继承该抽象类时,TypeScript报错:Property #recordNumber from class AbstractRecord is not implemented,子类代码如下:
class UserRecord extends AbstractRecord { #firstName: string; #lastName: string; constructor() { super(); } get firstName(): string { return this.#firstName; } set firstName(arg: string) { this.#firstName = arg; } get lastName(): string { return this.#lastName; } set lastName(arg: string) { this.#lastName = arg; } get fullName(): string { return `${this.firstName} ${this.lastName}`; } }
虽然编译可以正常完成,但报错影响开发体验。如果把#recordNumber设为可选字段,子类不再报错,但需要修改getter为return this.#recordNumber || null,这在构造函数已经初始化该字段为null的情况下完全冗余。
问题原因
TypeScript中,以#开头的私有字段是真正的类私有成员,它只属于定义它的类本身,不会被子类继承,也无法被子类访问。抽象类中定义这样的私有字段时,TypeScript会错误地要求子类实现该字段,这是私有字段的设计特性导致的。
解决方案
将私有字段改为protected修饰的受保护字段,这样既可以保持封装性(外部无法直接访问),又能让子类继承该字段,不需要额外实现:
修改后的AbstractRecord代码:
export abstract class AbstractRecord { protected recordNumber: null | string; protected constructor() { this.recordNumber = null; } get recordNumber(): null | string { return this.recordNumber; } set recordNumber(arg: null | string) { this.recordNumber = arg; } }
这样修改后,子类UserRecord继承时不会再报错,同时外部依然只能通过getter/setter来访问recordNumber字段,完全满足原有的需求,也避免了可选字段方案的冗余代码。
内容的提问来源于stack exchange,提问作者Zach
相关产品推荐
相关产品推荐

