TypeScript 的类型系统是它的一个重要特性,它可以在编译时检查类型错误,提高代码的可靠性和可维护性。但是,在实际开发中,我们经常需要与其他库或框架进行交互,这时就需要考虑 TypeScript 的兼容性问题。
TypeScript 的兼容性规则是基于结构子类型化(structural subtyping)的,也就是说,只要两个类型的结构相似,它们就是兼容的。
一.基本数据类型的兼容性
let temp: string | number;
let num!: number;
temp = num;
你要的我有就可以
let num: {
toString(): string;
};
let str: string = "james";
num = str; // 字符串中具备toString()方法,所以可以进行兼容
二.接口兼容性
interface IAnimal {
name: string;
age: number;
}
interface IPerson {
name: string;
age: number;
address: string;
}
let animal: IAnimal;
let person: IPerson = {
name: "zf",
age: 11,
address: "回龙观",
};
animal = person;
接口的兼容性,只要满足接口中所需要的类型即可!
三.函数的兼容性
函数的兼容性主要是比较参数和返回值
-
参数
let sum1 = (a: string, b: string) => a + b; let sum2 = (a: string) => a; sum1 = sum2;赋值函数的参数要少于等于被赋值的函数,与对象相反,例如:
type Func<T> = (item: T, index: number) => void; function forEach<T>(arr: T[], cb: Func<T>) { for (let i = 0; i < arr.length; i++) { cb(arr[i], i); } } forEach([1, 2, 3], (item) => { console.log(item); }); -
返回值
type sum1 = () => string | number; type sum2 = () => string; let fn1: sum1; let fn2!: sum2; fn1 = fn2;
四.函数的逆变与协变
函数的参数是逆变的,返回值是协变的 (在非严格模式下函数的参数是双向协变的)
class Parent {
address: string = "回龙观";
}
class Child extends Parent {
money: number = 100;
}
class Grandsom extends Child {
name: string = "吉姆";
}
type Callback = (person: Child) => Child;
function execCallback(cb: Callback) {}
let fn = (person: Parent) => new Grandsom();
execCallback(fn);
通过这个案例可以说明,函数参数可以接收父类,返回值可以返回子类
五.类的兼容性
class Parent {
name: string = "james";
age: number = 18;
}
class Parent1 {
name: string = "james";
age: number = 18;
}
let parent: Parent = new Parent1();
这里要注意的是,只要有 private 或者 protected 关键字类型就会不一致;但是继承的类可以兼容
class Parent {
private name: string = "james";
age: number = 18;
}
class Parent1 {
name: string = "james";
age: number = 18;
}
let parent: Parent = new Parent1();
// Type 'Parent1' is not assignable to type 'Parent'.
// Property 'name' is private in type 'Parent' but not in type 'Parent1'.
class Parent1 {
protected name: string = "zf";
age: number = 11;
}
class Child extends Parent1 {}
let child: Parent1 = new Child();
六.泛型的兼容性
interface IT<T> {}
let obj1: IT<string>;
let obj2!: IT<number>;
obj1 = obj2;
七.枚举的兼容性
enum USER1 {
role = 1,
}
enum USER2 {
role = 1,
}
let user1!: USER1;
let user2!: USER2;
user1 = user2; // 错误语法
// Type 'USER2' is not assignable to type 'USER1'.ts(2322)
不同的枚举类型不兼容