跳到主要内容

类型兼容

类型兼容

interface Pet {
name: string;
}
class Dog {
name: string;
}
let pet: Pet;
// OK, because of structural typing
pet = new Dog();

如上所示,Dog实例之所以可以赋值给pet是因为其具有相同的成员name,由于 JavaScript 大量使用对象字面量、函数表达式等匿名对象,因此用结构类型系统而不是名义类型系统来表示 JavaScript 库中的各种关系要自然得多

基本规则

  • 至少具有相同成员x
interface Pet {
name: string;
}
let pet: Pet;
// dog's inferred type is { name: string; owner: string; }
let dog = { name: 'Lassie', owner: 'Rudd Weatherwax' };
pet = dog;

如何检查dog是否可以赋值给pet,编译器首先检查pet的每个属性是否能在dog中找到对应的属性,如果存在,那么允许赋值。就像买东西,如果一家超市可以满足我清单上所有的需求,不管这个超市还有什么,这个超市就是“类型兼容的”

m

需要注意的是,比较会递归检查成员以及子成员

函数比较

参数比较

let x = (a: number) => 0;
let y = (b: number, s: string) => 0;
y = x; // OK
x = y; // Error

我们首先检查参数列表,需要注意的是,检查的是参数类型而非参数名

为什么 y=x 是被允许的呢,因为忽略一些参数在 JavaScript 中相同常见,比如

let items = [1, 2, 3];
// Don't force these extra parameters
items.forEach((item, index, array) => console.log(item));
// Should be OK!
items.forEach((item) => console.log(item));

接着我们来比较函数返回值

let x = () => ({ name: 'Alice' });
let y = () => ({ name: 'Alice', location: 'Seattle' });
x = y; // OK
y = x; // Error, because x() lacks a location property
信息
  • 行指示待分配的内容
  • 列指示分配的对象
  • 参考顺序:object = null->
  • ✓ 需要关闭 strictNullChecks
type Col= null
type Row = object

let aa:Row;
let bb:Col;
bb=aa // Type 'object' is not assignable to type 'null'.
aa=bb

类型系统强制要求函数返回值得是目标类型的子类型

https://www.typescriptlang.org/docs/handbook/type-compatibility.html

https://www.typescriptlang.org/docs/handbook/2/objects.html#excess-property-checks