TypeScript 的协变、逆变、双向协变、不变
TypeScript
给 JavaScript
添加了一套静态类型系统,是为了保证类型安全的,也就是保证变量只能赋同类型的值,对象只能访问它有的属性、方法。
但是这种类型安全的限制也不能太死板,有的时候需要一些变通,比如子类型是可以赋值给父类型的变量的,可以完全当成父类型来使用,也就是“型变(variant)”(类型改变)。
这种“型变”分为两种,一种是子类型可以赋值给父类型,叫做协变(covariant),一种是父类型可以赋值给子类型,叫做逆变(contravariant)。
协变
子类型可以赋值给父类型的情况就叫做协变(covariant)。
1 | interface Person { |
逆变
函数的参数有逆变(contravariant)的性质,即拥有父类型参数的函数可以赋值给子类型的函数。而返回值是协变的,也就是子类型可以赋值给父类型。
1 | interface Person { |
双向协变
在 ts2.x 之前支持有父类型参数的函数可以赋值给子类型的函数(协变),同时有子类型参数的函数可以赋值给父类型的函数(逆变)。这种特性成为“双向协变”。
但是这明显是有问题的,不能保证类型安全,所以之后 ts 加了一个编译选项 strictFunctionTypes
,设置为 true
就只支持函数参数的逆变,设置为 false
则支持双向协变。
1 | printName = printSubjects; // 将 strictFunctionTypes 设为 false 后,支持函数参数的双向协变,类型检查不会报错,但不能严格保证类型安全。 |
不变
型变都是针对父子类型来说的,非父子类型就不会型变也就是不变(invariant)。
参考
相关文章