如何使用JSDoc覆盖继承类方法的返回值类型
问题背景
需要实现:通过向父类构造函数传入子类构造函数的方式,让继承自父类的方法自动返回对应子类的实例类型,实现动态类型推断。
当前已知的冗余方案是在每个子类中手动声明所有继承自父类的方法,方法内部调用super()执行原有逻辑,但该方案代码冗余,不符合简洁性要求。需要找到正确的JSDoc泛型标注写法,或确认需求可行性。
问题复现
原有未生效的实现代码如下:
/** * The Animal base class * @class */ class Animal { /** * @param {T} classType */ constructor (classType) { this.classType = classType } /** * @returns {T} A baby of the same type as the parent instance */ giveBirth () { return new this.classType() } } /** * The Dog class * @class * @extends Animal */ class Dog extends Animal { constructor () { super(Dog) } bark () { return 'woof' } } const dog = new Dog() const babyDog = dog.giveBirth() babyDog.bark() // JSDoc无法识别babyDog为Dog实例,报类型错误
可行解决方案
该需求完全可以通过正确的JSDoc泛型标注实现,不需要在子类重复编写父类方法,修正后的代码如下:
/** * 动物基类 * @class * @template {new () => Animal} T - 子类构造函数类型约束 */ class Animal { /** * @param {T} classType 对应子类的构造函数 */ constructor (classType) { /** @type {T} */ this.classType = classType } /** * 生育幼崽 * @returns {InstanceType<T>} 与当前实例同类型的幼崽实例 */ giveBirth () { return new this.classType() } } /** * 狗类 * @class * @extends {Animal<typeof Dog>} */ class Dog extends Animal { constructor () { super(Dog) } bark () { return 'woof' } } const dog = new Dog() const babyDog = dog.giveBirth() babyDog.bark() // 类型推断正常,无报错
标注要点说明
- 给基类
Animal声明泛型参数T时,必须加类型约束{new () => Animal},限定T是返回Animal子类实例的无参构造函数,避免传入非法类型 - 父类
giveBirth方法的返回值不能直接写T,T是构造函数类型,需要用内置工具类型InstanceType<T>获取构造函数对应的实例类型 - 子类继承父类时,必须通过
@extends {Animal<typeof Dog>}显式传入泛型参数,告知类型系统当前子类对应的构造函数是自身的构造器,否则类型系统无法将泛型T和子类关联 - 类内部的
classType属性最好也补充@type {T}标注,避免属性类型推断丢失
内容的提问来源于stack exchange,提问作者Tom Nijs
相关产品推荐
相关产品推荐

