TS:类型的推论兼容
1. 变量类型兼容
-
若变量x要兼容y,那么y必须至少拥有与x相同的属性:
interface Named { name : string; } let x : Named; let y = { name : 'yivi',age : 12 }; x = y; // ok,y中拥有x的属性name
2. 函数类型兼容
-
首先是参数兼容:要看函数x能否赋值给y,x的每一个参数必须在y里能找到对应类型的参数。(参数名字无所谓,类型一致即可)。
let x = (a: number) => 0; let y = (b: number , s:string) => 0; y = x; // ok x = y; //error,x中缺少y的多余参数。
-
其次是返回值兼容:原函数的返回值类型必须是目标函数返回值类型的子类型。
let x = () => ({ name : 'yivi'}); let y = () => ({ name : 'yivi',age : 20}); x = y; // ok y = x; // error,x的返回值缺少参数。
3. 可选参数和剩余参数的不稳定性
-
当一个函数有剩余参数时,它将被当作无限个可选参数;
-
这对于类型系统来说是不稳定的,但从运行上看,对大多数函数来说相当于传递路
undefined
。 -
回调函数里的参数对于程序员来说是可预知的,但对类型系统来说是不确定的。
function foo(args : any[],callback : (...args : any[]) => void){ // 程序实现 }
4. 枚举兼容
-
枚举类型与数字类型互相兼容;
-
不同枚举类型之间是互不兼容的;
enum A { OK,ERROR}; enum B { SUCCESS,FAILED}; let status = A.OK; status = B.SUCCESS; //error!
5. 类兼容
-
比较两个类 类型 的 对象时,只有实例的成员会被比较。
-
静态成员和构造函数并不包含在内!!!
class Cat { kind : string; constructor(name : string,size : number){ } } class Dog { kind : string; constructor(name : string){ } } let c : Cat; let d : Dog; c = d; //ok d = c; //ok
6. 泛型兼容
-
类型参数之影响使用其作为类型一部分的结果类型。
interface Empty<T> { } let x : Empty<number>; let y : Empty<string>; x = y; //ok,由于接口里没有成员,所以y的结构和x一致
-
但接口里有成员就时另外一回事儿了:
interface Full<T> { data : T } let x : Full<number>; let y : Full<string>; x = y; // error!x和y的结构不一致!