赋值兼容性
TypeScript 中存在两种兼容性,即子类型兼容性和赋值兼容性。子类型兼容性与赋值兼容性有着密切的联系,若类型 S
是类型 T
的子类型,那么类型 S
能够赋值给类型 T
。在赋值语句中,变量和表达式之间需要满足赋值兼容性;在函数调用语句中,函数形式参数与实际参数之间也要满足赋值兼容性。示例如下:
type T = { x: number };
type S = { x: number; y: number };
let t: T = { x: 0 };
let s: S = { x: 0, y: 0 };
t = s;
function f(t: T) {}
f(t);
f(s);
此例中,S
是 T
的子类型,那么 S
可以赋值给 T
,同时可以使用 S
来调用接收 T
类型参数的函数。
子类型兼容性
在绝大多数情况下,如果类型 S
能够赋值给类型 T
,那么也意味着类型 S
是类型 T
的子类型。针对这个规律只有以下几种例外情况。
-
any
类型。在赋值兼容性中,any
类型能够赋值给任何其他类型,但any
类型不是其他类型的子类型,因为any
类型是顶端类型。 -
数值型枚举与
number
类型。number
类型可以赋值给数值型枚举类型,但number
类型不是数值型枚举的子类型,反而数值型枚举是number
类型的子类型。示例如下:enum E { A, B, } const s: number = 0; const t: E = s;
-
带有可选属性的对象类型。如果对象类型
T
中有可选属性M
,那么对象类型S
也可以赋值给对象类型T
,即使S
中没有属性M
。示例如下:
type T = { x: number; y?: number };
type S = { x: number };
const s: S = { x: 0 };
const t: T = s;
此例中,类型 S
能够赋值给类型 T
,但是类型 S
不是类型 T
的子类型,因为类型 T
中的属性 y
不能够在类型 S
中找到对应的属性定义。