Mei*_*des 6 generics typescript typescript-generics
假设您有以下代码:
class Superclass<T>{
combine(object: Superclass<T>) {
console.log("combined!");
return object;
}
}
class Generic1 {
x = 12;
// some class...
}
class Generic2 {
y = "Hello!";
// some class...
}
new Superclass<Generic1>().combine(new Superclass<Generic2>());
Run Code Online (Sandbox Code Playgroud)
你肯定会注意到,这里应该有一个错误。Superclass<Generic1>只能与 结合Superclass<Generic1>,但决不能与 结合Superclass<Generic2>。Visual Studio 代码也显示:
但是编译后没有错误!为什么?我误解了泛型吗?
TypeScript 允许它通过,因为TinSuperclass<T> 不影响它的 shape,因此Superclass<A>和Superclass<B>具有相同的形状,因此被 TypeScript 认为是“兼容的”。
请记住,TypeScript 有一个结构类型系统,其中的成员认为类型是等效的,即使它们的实际定义和原始定义是完全分开的(想想收敛进化)。至于为什么是令人惊讶:请记住,打字稿也不能有记名式系统,其中类型具有相同的成员,结构和布局,一直到跨平台的二进制表示,被认为是严格的区别,只要它们有不同的类型-名称(这是 Java、C# 和许多其他语言的类型系统的工作方式)。
所以 whileSuperclass<T>不使用T并且不影响它的形状,所以tsc认为是T多余的而忽略它:
所以这...
class Superclass<T> {
combine(object: Superclass<T>): Superclass<T> { ... }
}
Run Code Online (Sandbox Code Playgroud)
...可证明等价于:
class Superclass {
combine(object: Superclass): Superclass { ... }
}
Run Code Online (Sandbox Code Playgroud)
但是,一旦Superclass<T>变得依赖于T,例如通过添加类型为 的字段T,则会引发错误:
class Superclass<T>{
public value: T;
constructor(value: T) {
this.value = value;
}
combine(object: Superclass<T>) {
console.log("combined: " + object.value.toString());
return object;
}
}
class Generic1 {
x = Math.random();
}
class Generic2 {
y = Math.random();
}
var x = new Superclass<Generic1>( new Generic1() ).combine(new Superclass<Generic2>( new Generic2() ) );
Run Code Online (Sandbox Code Playgroud)
错误:
Argument of type 'Superclass<Generic2>' is not assignable to parameter of type 'Superclass<Generic1>'.
Property 'x' is missing in type 'Generic2' but required in type 'Generic1'.
Run Code Online (Sandbox Code Playgroud)
至于为什么会这样- 这是(我认为)在 TypeScript 文档中关于Type Compatibility的部分中解释的:
TypeScript 的结构类型系统的基本规则
x是与yify至少具有相同的成员x
在这种情况下, whenSuperclass<T>是关闭的,因为其中一个Superclass<Generic1>或Superclass<Generic2>两个类型具有完全相同的成员,并且 TypeScript 认为它们彼此兼容。
| 归档时间: |
|
| 查看次数: |
43 次 |
| 最近记录: |