面试题答案
一键面试- 类型兼容性规则:
- 在TypeScript中,对于函数类型的兼容性,是基于参数和返回值的兼容性来判断的。
- 对于函数参数,是基于逆变(contravariance)规则。即目标类型(这里是
Fn2
)的参数类型必须能接受源类型(这里是Fn1
)的参数类型。 - 对于函数返回值,是基于协变(covariance)规则。即源类型的返回值类型必须能赋值给目标类型的返回值类型。
- 分析返回值兼容性:
Fn1<T extends { a: number }> = (arg: T) => T['a'];
的返回值类型是T['a']
,其中T
约束为包含a
属性且类型为number
。Fn2<T extends { a: number, b: string }> = (arg: T) => T['a'];
的返回值类型同样是T['a']
,其中T
约束为包含a
属性且类型为number
以及b
属性且类型为string
。- 由于
Fn1
和Fn2
的返回值类型都是number
(因为T['a']
都是number
类型),根据协变规则,Fn1
的返回值类型能赋值给Fn2
的返回值类型。
- 分析参数兼容性:
Fn1
的参数类型是T
,其中T
只要求包含a
属性且类型为number
。Fn2
的参数类型是T
,其中T
要求包含a
属性且类型为number
以及b
属性且类型为string
。- 根据逆变规则,
Fn1
的参数类型要能赋值给Fn2
的参数类型。然而,Fn1
的参数类型可能不包含b
属性,而Fn2
的参数类型要求必须包含b
属性。所以,Fn1
的参数类型不能赋值给Fn2
的参数类型。
- 结论:
- 在严格的类型检查下(默认编译选项),
Fn1
类型的函数不能赋值给Fn2
类型的函数,因为函数参数类型不满足逆变规则。 - 如果关闭严格的函数参数检查(例如设置
"strictFunctionTypes": false
),那么Fn1
类型的函数可以赋值给Fn2
类型的函数,因为此时放宽了函数参数类型的逆变规则要求,只比较返回值类型,而它们的返回值类型是兼容的。
- 在严格的类型检查下(默认编译选项),