typescript - 为什么变量是未知的?
请看这个例子。我想知道为什么在函数 test2 中 p 参数是未知的。我原以为 p 会被作为一个数字已知。
interface MyInterface<A,B>{}
class MyClass<A,B> implements MyInterface<A,B> {}
function test1<A,B>(p:MyClass<A,B>, callback:(p:B)=>void){}
function test2<A,B>(p:MyInterface<A,B>, callback:(p:B)=>void){}
const myInstance = new MyClass<string,number>()
test1(myInstance, (p)=>{
// Here p is a number
})
test2(myInstance, (p)=>{
// Why is p unknown?
})
答案#1
这是因为你的接口是空的;在像 TypeScript 这样的结构类型系统中,空接口会被每个类实现,无论该类实际上拥有什么成员。因此,你的类不仅实现了 MyInterface<A, B>,还实现了 MyInterface<boolean, string> 以及 MyInterface 类型参数的每一种可能赋值,因为它(显而易见地)拥有实现这些类型参数接口所需的所有成员,无论它是否通过 implements 子句显式声明了这一点。
因此,Typescript 无法推断 test2 的 A 和 B 应该是什么类型,因为实际上任何类型都是兼容的;例如,test2<boolean, string>(myInstance, (p) => { /* ... */ }) 可以编译且没有错误,并且 p 的类型是 string。
如果接口有一个成员(并且类实现了它),使得参数化该类的 A 和 B 必须与参数化接口的相同,那么 p 的类型将在两个函数中被正确推断:
interface MyInterface<A,B>{
foo(x: A, y: B): void;
}
class MyClass<A,B> implements MyInterface<A,B> {
foo(x: A, y: B): void {}
}
test2(myInstance, (p)=>{
// p: number
})
游乐场链接
