TypeScript继承:父类使用、仅子类定义的数据成员应如何声明
原代码问题梳理
原代码存在两处核心问题:
- 父类
some_function方法存在笔误,将this.value写为this.val,运行时会直接抛出未定义错误 - 父类声明的
protected value: number未在父类构造函数中初始化,仅在子类中赋值,若父类方法在子类初始化完成前被调用,会拿到undefined,和声明的number类型冲突,触发运行时异常
正确实现方案
方案1:使用抽象类+抽象属性(最推荐)
如果该属性必须由所有继承的子类提供,父类本身不需要也不能直接实例化,直接将父类定义为抽象类,属性声明为抽象属性,强制子类必须实现该属性,TS编译阶段就会做检查,从根源避免属性未赋值的问题:
abstract class Parent { foo: number; // 声明抽象属性,强制所有子类必须实现该属性 protected abstract value: number; constructor(foo: number) { this.foo = foo } some_function() { return this.foo + this.value } } class ChildClass extends Parent { // 子类必须实现抽象属性,否则TS会直接编译报错 protected value: number; constructor(foo: number) { super(foo); this.value = 10; } }
方案2:属性声明为允许undefined类型,使用时加类型守卫
如果父类需要支持直接实例化,没有强制要求子类必须传该属性,可以明确声明属性可能为undefined,用到的地方做兼容处理:
class Parent { foo: number; // 明确声明value可能为undefined protected value: number | undefined; constructor(foo: number) { this.foo = foo } some_function() { // 加类型守卫,处理属性未赋值的情况 if (this.value === undefined) { throw new Error('value属性未初始化,请先完成赋值再调用该方法'); // 也可以设置 fallback 逻辑:return this.foo + 0 } return this.foo + this.value } } class ChildClass extends Parent { constructor(foo: number) { super(foo); this.value = 10; } }
方案3:父类给属性设置默认值
如果该属性有通用的默认值,可以直接在父类中设置默认值,子类可以选择是否覆写:
class Parent { foo: number; // 父级设置默认值 protected value: number = 0; constructor(foo: number) { this.foo = foo } some_function() { return this.foo + this.value } } class ChildClass extends Parent { constructor(foo: number) { super(foo); // 子类覆写默认值 this.value = 10; } }
内容的提问来源于stack exchange,提问作者Sid Anand
相关产品推荐
相关产品推荐

