在派生 class 中更正扩展构造函数参数的 TypeScript 类型
Correct TypeScript types for extended constructor parameter in derived class
我有一个带有 BaseParams
构造函数参数的 Base
class,我想从 Base
扩展一个 Derived
class,它接受一个 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
赋值覆盖传递给 [=19= 的 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
class 中,this.params
是 ExtendedParams
类型, 和 默认值被传递给 super()
调用并且 this.params
之后没有被覆盖?
但是从 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
}
}
我有一个带有 BaseParams
构造函数参数的 Base
class,我想从 Base
扩展一个 Derived
class,它接受一个 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
赋值覆盖传递给 [=19= 的 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
class 中,this.params
是 ExtendedParams
类型, 和 默认值被传递给 super()
调用并且 this.params
之后没有被覆盖?
但是从 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
}
}