结构类型系统
接口的兼容性
- 如果传入的变量和声明的类型不匹配,TS就会进行兼容性检查。
- 原理是
Duck-Check
,就是说只要目标类型中声明的属性变量在源类型中都存在就是兼容的。
interface Animal {
name: string;
age: number;
}
interface Person {
name: string;
age: number;
gender: number
}
// 要判断目标类型`Person`是否能够兼容输入的源类型`Animal`
function getName(animal: Animal): string {
return animal.name;
}
let p:Person= {
name: 'x',
age: 10,
gender: 0
}
getName(p);
//只有在传参的时候两个变量之间才会进行兼容性的比较,赋值的时候并不会比较,会直接报错
let a: Animal = {
name: 'x',
age: 10,
gender: 0
}
基本类型的兼容性
//基本数据类型也有兼容性判断
let num : string|number;
let str:string='x';
num = str;
//只要有toString()方法就可以赋给字符串变量
let num2 : {
toString():string
}
let str2:string='x';
num2 = str2;
类的兼容性
class Animal{
name:string
}
class Bird extends Animal{
swing:number
}
let a:Animal;
a = new Bird();
let b:Bird;
//并不是父类兼容子类,子类不兼容父类
b = new Animal();
在TS中是结构类型系统,只会对比结构而不在意类型。
class Animal{
name:string
}
//如果父类和子类结构一样,也可以的
class Bird extends Animal{}
let a:Animal;
a = new Bird();
let b:Bird;
b = new Animal();
//甚至没有关系的两个类的实例也是可以的
class Animal2{
name:string
}
class Bird2{
name:string
}
let a:Animal2 ;
a = new Bird2();
let b:Bird2;
b = new Animal2();
函数的兼容性
比较函数的时候是要先比较函数的参数,再比较函数的返回值。
type sumFunc = (a:number,b:number)=>number;
let sum:sumFunc;
function f1(a:number,b:number):number{
return a+b;
}
sum = f1;
//可以省略一个参数
function f2(a:number):number{
return a;
}
sum = f2;
//可以省略二个参数
function f3():number{
return 0;
}
sum = f3;
//多一个参数可不行
function f4(a:number,b:number,c:number):number{
return a+b+c;
}
sum = f4;
函数参数的协变
当比较函数参数类型时,只有当源函数参数能够赋值给目标函数或者反过来时才能赋值成功。
type logFunc = (a:number|string) =>void;
let log:logFunc;
log = (a:number)=>{}//不行
log = (a:number|string|boolean)=>{}; //可以
泛型的兼容性
泛型在判断兼容性的时候会先判断具体的类型,然后再进行兼容性判断。
//接口内容为空没用到泛型的时候是可以的
//1.接口内容为空没用到泛型的时候是可以的
interface Empty<T>{}
let x:Empty<string>;
let y:Empty<number>;
x = y;
//2.接口内容不为空的时候不可以
interface NotEmpty<T>{
data:T
}
let x1:NotEmpty<string>;
let y1:NotEmpty<number>;
x1 = y1;
//实现原理如下,称判断具体的类型再判断兼容性
interface NotEmptyString{
data:string
}
interface NotEmptyNumber{
data:number
}
let xx2!:NotEmptyString;
let yy2!:NotEmptyNumber;
xx2 = yy2;
枚举的兼容性
- 枚举类型与数字类型兼容,并且数字类型与枚举类型兼容。
- 不同枚举类型之间是不兼容的。
//数字可以赋给枚举
enum Colors {Red,Yellow}
let c:number = Colors.Red;