TS高级-类型兼容(协变、逆变、双向协变)
类型兼容
所谓的类型兼容性,就是用于确定一个类型是否能赋值给其他的类型。typeScript 中的类型兼容性是基于结构类型的(也就是形状),如果 A 要兼容 B 那么 A 至少具有 B 相同的属性。
协变
如果类型 S 可以赋值给类型 T,那么我们就说类型 T 是类型 S 的协变类型。简单来说,就是子类型可以赋值给父类型,子类型中的属性必须完全覆盖父类型中的属性。
而这类型也被称为鸭子类型(一只鸟走路像鸭子,游泳也像,做什么都像鸭子,那么这只鸟就可以成为鸭子类型)。
// 父类型
interface A {
name: string;
age: number;
}
// 子类型
interface B {
name: string;
age: number;
sex: string;
}
let a: A = {
name: "张三",
age: 18,
};
let b: B = {
name: "李四",
age: 19,
sex: "女",
};
// 父 = 子
a = b; // 协变
协变是针对值的。
逆变
协变赋值的相反操作,对于函数来说,拥有父类型的函数赋值给子类型的函数:
let fnA = (params: A) => {};
let fnB = (params: B) => {};
// 子 = 父
fnB = fnA; // 逆变
逆变是针对函数(函数参数)的。
双向协变
是子类型和父类型可以互相赋值。
注意:这在 TypeScript2.0 之前允许这么操作,TypeScript2.0 之后发现这样是不安全的,如果你需要支持双向协变的话需要自己去开启这个属性:
// tsconfig.json "compilerOptions": { "strictFunctionTypes": false, }