大佬教程收集整理的这篇文章主要介绍了为什么在泛型上使用 InstanceType 是错误的,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
为什么在泛型上使用 InstanCEType
是错误的?是协变的还是逆变的?
interface Ctor {
new(): Instance;
}
interface Instance {
print(): voID;
}
function f1<T extends Ctor>(ctor: T) {
// Error: Type 'Instance' is not assignable to Type 'InstanCEType<T>'
const ins: InstanCEType<T> = new ctor();
ins.print();
}
function f2(ctor: Ctor) {
// No error
const ins: InstanCEType<Ctor> = new ctor();
ins.print();
}
Playground Link
这是我认为的问题:Typescript 通过查看 new ctor()
的类型(即 ctor
)来确定表达式 T
的编译时类型,检查 { {1}} 必须有一个构造函数签名(确实如此),然后找到 T
的构造函数签名返回的内容。但是 T
可以是 T
的任何子类型,因此它的构造函数签名可以返回 Ctor
的任何子类型。
在这种情况下,编译器可以做两件合理的事情:
Instance
),并让表达式R extends Instance
的类型为new ctor()
,R
。Typescript 做后者,也许是因为 Typescript 只有在你告诉它的情况下才会创建类型变量;它从不隐含地这样做。这使表达式的类型比赋值给 Instance
以进行类型检查所需的类型更弱,因为 InstanCEType<T>
确实 显式地创建了一个类型变量 InstanCEType<T>
(使用 {{ 1}} 子句),可以是 R
的任意子类型。
所以表达式 infer
的类型是 Instance
,但是赋值目标的类型注解是(不是真的,而是某种意义上)一个类型变量 {{1 }} 可以是 new ctor()
的任何子类型,因此存在类型错误。
一个可能的解决方案是为返回类型显式创建一个类型变量,如下所示:
Instance
也就是说,只有当您的函数以其他方式处理 R
时才值得这样做,例如具有涉及 Instance
的返回类型。否则,您使用 function f1<R extends Instance,T extends {new(): R}>(ctor: T) {
const ins: R = new ctor();
ins.print();
}
的代码必须适用于 R
的任何实现,包括 R
本身,因此无论如何您也可以将其类型声明为 ins
。 (同样,如果您的函数没有在其他任何地方使用 R
,您不妨改为将参数类型设为 Instance
)。
因为你说 T 扩展了 Ctor,这意味着它不完全是一个 Ctor。它可能有一个返回 Instance|Instance2 的 new。打字稿无法知道。而且由于 Ctor 声明它总是从它的构造函数返回一个实例,它不知道正确派生的正确类型。
如果您希望它与泛型和派生类型一起使用,您需要允许它使用泛型参数推断派生类型。
interface Ctor<Tinstance extends Instance> {
new(): Tinstance;
}
interface Instance {
print(): void;
}
function f1<Tinstance extends Instance>(ctor: Ctor<Tinstance>) {
const ins: Tinstance = new ctor();
ins.print();
}
以上是大佬教程为你收集整理的为什么在泛型上使用 InstanceType 是错误的全部内容,希望文章能够帮你解决为什么在泛型上使用 InstanceType 是错误的所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。