typescript 从子类调用的构造函数参数推断类型
Posted
技术标签:
【中文标题】typescript 从子类调用的构造函数参数推断类型【英文标题】:typescript infer type from constructor argument called by sub class 【发布时间】:2021-05-30 03:50:31 【问题描述】:我有一个带有一些属性/方法的类,这些属性/方法返回最初通过构造函数传递的值:
class Base
constructor(arg)
this.options = arg.options;
人们建议使用泛型作为打字稿等价物的此类:
class Base<T extends options: any>
options: T["options"];
constructor(arg: T)
this.options = arg.options;
// works fine with instantiation
const inst = new Base(options: foo: 123);
inst.options.foo++; // ok
inst.options.bar; // TS Error
现在我有一个子类,它调用超类的构造函数并传递这些选项:
class Sub extends Base // TS Error
constructor()
super(options: foo: 123);
this.options.foo++; // TS Error
Typescript 编译器对此并不满意,并希望通过该类型扩展基类。但后来我有两次信息,在超级调用和扩展符号中。解决我的问题的正确 ts 语法是什么?
(typescript playground 中的代码)
【问题讨论】:
您的游乐场链接被切断,因此代码被切断。它只是问题中的代码吗?如果是这样,我已经解决了。如果没有,请将代码同时添加到操场和问题中。 :-) 你传递的值super
真的是编译时文字吗?
FWIW,我怀疑你可以让 TypeScript 从 super
调用中推断出 Base
的类型参数。我怀疑options: foo: number
和options: foo: 123
的近乎重复是不可避免的。
@T.J.Crowder,我修复了链接。是的,该值在代码中是固定的,不会在运行时读取/构建。它实际上定义了这个特定类具有哪些特征,并且超类在 ctor 中提供了这个参数来动态生成这些特征。 (如果这有意义的话)当通过 new
关键字调用 Base 类时,TS 能够以某种方式提取一些类型信息。所以我希望在扩展课程时同样的逻辑可以工作。但它只需要对 ts 代码进行一些更改。
【参考方案1】:
编辑:
问题不在于super()
,而在于extends Base
。无论如何,typescript 必须推断 Base 的泛型类型,而您不能指望 typescript 从对 super()
的调用中推断出这一点。
一开始我会建议这样做
class Sub<T extends options: any> extends Base<T>
constructor()
super(options: foo: 123)
但这在a concrete instance is not allowed to be assigned to a type parameter 之后将不起作用。如果我们改为这样做,它会起作用的
class Sub<T extends options: any> extends Base<T>
constructor(arg: T)
super(arg)
const inst2 = new Sub(options: foo: 123)
inst2.options.foo++; // ok
我认为正确的解决方案是简单地这样做
class Sub extends Base<options: any>
constructor()
super(options: foo: 123)
但是,还是有问题。
const inst2 = new Sub();
inst2.options.foo++; //options is any which makes sense, we said that options is any above
你知道我们为什么使用泛型吗?当我们事先不知道类型是什么时。由于在这种情况下我们确切地知道类型是什么,所以我们可以安全地这样做:
class Sub extends Base< options: foo: number >
// or even class Sub extends Base< options: foo: 123 >
constructor()
super(options: foo: 123);
this.options.foo++;
const inst2 = new Sub();
inst2.options.foo++;
这样做可以吗?当然,如果我们将选项以外的东西传递给Base
,就会触发警告。所以我们满足Base
的要求,同时确保我们传递给super()
的东西和我们所说的泛型类型是一致的。
【讨论】:
以上是关于typescript 从子类调用的构造函数参数推断类型的主要内容,如果未能解决你的问题,请参考以下文章
我可以从Typescript中的父类的构造函数触发子类的成员函数吗?