interface X { a: any, b: any } interface Y { a: any, b: any, c: any } let x: X = { a: 1, b: 2 } let y: Y = { a: 1, b: 2, c: 3 } y = x //y接口要求要有三个属性,而x有两个,满足条件
//1. 参数个数 let handle1 = (a: number) => { } hof(handle1) let handle2 = (a: number,b: number,c: number) => { } hof(handle2) // Handler需要两个参数,而这里给了三个,则不满足条件 // 可选参数 let a = {p1: number, p2: number} => {} let b = {p1?: number, p2?: number} =>{} let c = (...args: number[]) => {} a = b a = c // 固定参数可以兼容可选参数和剩余参数 b = c b = a //错误 // 可选参数不兼容固定参数和剩余参数
//3. 返回值类型 let f = () => ({ name: 'Alice' }) let g = () => ({ name: 'Alice', location: 'Beijing' }) f = g g = f // 错误
枚举兼容
1 2 3 4 5
enum Fruit { Apple, Banana } enum Color { Red, Blue } let fruit: Fruit.Apple = 3 let no: number = Fruit.Apple let color: Color.Red = Fruit.Apple // 错误 // 枚举之前是不兼容的
类兼容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classA{ constructor(p: number, q: number) { } id: number = 1 private name: string = 'zhangsan' } classB{ static s = 1 constructor(p: number) { } id: number = 2 private name: string = 'zhangsan'//当类中有私有成员,不构成兼容,只有子类能够兼容 } let aa = new A(1, 2) let bb = new B(1) aa = bb // 静态成员和构造函数不参与比较,如果他们有相同的实例成员,他们的实例就可以兼容 bb = aa // 这里两个实例都具有相同的实例成员id
泛型兼容
1 2 3 4 5 6 7
interface Empty<T>{ value: T } let obj1: Empty<number> = {} //当接口中没有成员的时候可以兼容 let obj2: Empty<string> = {} //当接口中的类型参数 T 被接口成员使用了的时候,才会影响泛型的兼容性 obj1 = obj2
泛型函数
1 2 3 4 5 6 7 8 9
let log1 = <T>(x: T): T => { console.log('x'); return x } let log2 = <U>(y: U): U => { console.log('y'); return y } log1 = log2 // 当两个泛型函数的定义相同,但是没有指定类型参数,他们之间是可以兼容的
结构之间兼容:成员少的兼容成员多的
函数之间兼容:参数多的兼容参数少的
类型保护
ts能够在特定的区块中保证变量属于某种确定的类型
可以在此区块中放心的引用此类型的属性,或调用此类型的方法
1 2 3 4 5 6 7 8 9 10 11
//1. 使用 instanceof //2. 使用 in //3. 使用 typeof let a = String if (a instanceofString) { a.charAt(0) } elseif (a instanceofNumber) { a.toFixed(2) }