【问题标题】:Correct TypeScript types for extended constructor parameter in derived class派生类中扩展构造函数参数的正确 TypeScript 类型
【发布时间】:2020-07-20 08:02:24
【问题描述】:

我有一个带有BaseParams 构造函数参数的Base 类,并且想从Base 扩展一个Derived 类,它接受一个ExtendedParams 构造函数参数,并将其传递给super()有一些默认值。问题是我似乎无法为Derived 构造函数参数找到正确的访问修饰符和类型组合。

这是我目前所拥有的:

interface BaseParams {
  first: string;
}

interface ExtendedParams extends BaseParams {
  last?: string;
}

class Base {
  constructor(protected params: BaseParams) {}
  inspect(): void {
    console.log(this.params);
  }
}

class Derived extends Base {
  constructor(??? params ???) {
    super({ first: 'John', last: 'default', ...params });  // override default params with specified ones
    this.params.last;  // #1 - this should not generate any compile errors
    this.params.whatever = 'Wrong';  // #2 - TS should flag this as not existing on type ExtendedParams
  }
}

const d = new Derived({ first: 'Mike' });
d.inspect();  // #3 - should output { first: 'Mike', last: 'default', whatever: 'Wrong' }

我尝试将Derived params 声明为protected。这解决了 #1 和 #2。

class Derived extends Base {
  constructor(protected params: ExtendedParams) {
    super({ first: 'John', last: 'default', ...params });
    this.params.last;  // #1 - ok, no error
    this.params.whatever = 'Wrong';  // #2 - ok, flagged: `whatever` doesn't exist on type ExtendedParams
  }
}

问题在于last: 'default' 分配没有发生,因为protected 生成了一个this.params = params 分配覆盖了传递给super() 的params 值,所以d.inspect() 只输出{ first: 'Mike', whatever: 'Wrong' }。

我尝试省略 params 的访问修饰符。这会导致正确的输出{ first: 'Mike', last: 'default', whatever: 'Wrong' },但也会导致this.params.last 被标记为错误does not exist on type 'BaseParams'。

class Derived extends Base {
  constructor(params: ExtendedParams) {
    super({ first: 'John', last: 'default', ...params });
    this.params.last;  // #1 - wrong ly flagged 
    this.params.whatever = 'Wrong';  // #2 - ok, flagged
  }
}

是否有一些 TypeScript 魔法通知编译器在 Derived 类中,this.params 是 ExtendedParams 类型,并且默认值被传递给 super() 调用和 @ 987654349@之后不会被覆盖?

【问题讨论】:

    标签: typescript derived-class


    【解决方案1】:

    但是从Derived 你可以访问Base.params,它的类型很明显是BaseParams。

    如果您希望 params 属性更改派生类中的类型,则需要一个通用基类型:

    // <P = BaseParams> allows to instantiate Base with BaseParams as default type.
    class Base<P = BaseParams> {
        constructor(protected params: P) {}
        /* ... */
    }
    
    class Derived extends Base<ExtendedParams> {
        constructor(params: ExtendedParams) {
            super({ first: 'John', last: 'default', ...params });  // override default params with specified ones
            this.params.last;                // OK
            this.params.whatever = 'Wrong';  // Wrong
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-10
      • 2020-02-28
      • 1970-01-01
      • 1970-01-01
      • 2021-08-29
      • 2021-02-13
      • 1970-01-01
      • 2021-02-07
      • 1970-01-01
      相关资源
      最近更新 更多