类型兼容与赋值
为什么要有类型兼容
因为实际工作中,往往无法做到类型一致
比如在上面的 JS 代码中,假设 runTask
函数的参数只接受具有 a
、b
、c
这 3 个 key
的对象,但在一般情况下,即使我们多传一个 d
,也不会报错
你有的,我都有,则我能代替你;
y 有的,x 都有,则 x 兼容 y
简单类型的兼容
类型小的兼容类型大的
注意:图中的大小圆应当是包含关系,即小圆应该在大圆内部,此处为了展示清晰将小圆挪到了外部,后面的图示亦如此
集合 hi
小于集合 A
,因此将 hi
赋值给 a
不报错
普通对象的兼容
属性多的兼容属性少的
对象属性越多,限制越多,表示的集合范围越小,所以其实还是类型小的兼容类型大的
注意:对象兼容的前提是必须得存在共同的属性,此处两个对象共同的属性是
name
和age
兼容的情况下,作为参数也不报错
1 | type Person = { name: string; age: number } |
接口的兼容
子接口兼容父接口
函数的兼容
函数的兼容比较复杂,需要考虑参数和返回值
参数个数不同
存在相同类型的参数的函数,参数少的兼容参数多的
如何理解上图中的兼容关系?(图中绿色箭头代表可以兼容,红色箭头表示不能兼容)
如何理解上图中的代码?(图中绿色箭头代表可以兼容,红色箭头表示不能兼容)
主要看划线的右边参数的部分:
- 从上往下看,箭头全绿(
a
和b
都是number
) - 从下往上看,存在红色的箭头(参数
s
没有可以兼容的参数)
因此 接受一个参数的函数
兼容 接受两个参数的函数
,反过来则不行
为什么容忍参数变少呢?从下例中可以窥探一二
参数类型不同
对参数要求少的兼容对参数要求多的
从前面的例子我们知道,MyMouseEvent
是兼容 MyEvent
的,这里函数的兼容关系就正好反过来了。
返回值不同
不考虑参数类型的情况下,函数的兼容关系和返回值的兼容关系保持一致
思考:如果函数的参数和返回值同时存在且兼容关系相反呢?
实际工作中的函数
1 | interface Event { |
在不关闭 TS 严格检查的情况下,可以通过设置 "strictFunctionTypes": false
来避免函数报错
1 | // tsconfig.json |
特殊类型的兼容
顶类型(Top Type)与底类型(Bottom Type)
在 TS 中,顶类型(Top Type)表示可以接受任何值的类型,而底类型(Bottom Type)表示不可能有任何值的类型。
顶类型通常称为通用超类型,因为它是系统中所有其他类型的超类型。TS 提供了两种顶类型:any
和 unknown
。any
类型表示可以接受任何值,但它不提供任何类型检查。unknown
类型也可以接受任何值,但在使用之前必须先进行类型检查。
底类型通常称为通用子类型,因为它通常是系统中所有其他类型的子类型。TS 提供了一种底类型:never
。never
类型表示不可能有任何值,它用于表示永远不会返回值的函数或抛出异常的函数的返回类型。
1 | // Top Type 示例 |