React+TS中Props函数参数类型不生效 无参隐式类型疑问
TypeScript 函数类型赋值兼容性问题(React Props传参校验失效场景)
问题复现
在React结合TypeScript开发时,常遇到Props传递的函数参数类型校验不生效的问题,最小复现代码如下:
let a: (p: string) => void = (p) => {} a = (p: number) => {} a = () => '1' // 预期此处抛出类型错误
疑问梳理(2022-06-27更新)
在了解协变、逆变基础概念后,仍有两点存疑:
- 为什么无参数的函数类型
()是(p: string) => void的父类型? - 这个无参函数的隐式类型具体是什么?
问题解答
1. 无参函数可以赋值给带参函数的核心原因
TS的函数参数兼容性规则是主动贴合JavaScript实际运行逻辑设计的:JS调用函数时,不会强制要求传入的参数数量和函数声明的形参数量完全一致,传入多余的参数会被忽略,少传的参数会被赋值为undefined。
开发中这类场景非常普遍,比如数组的forEach方法会默认传入item、index、array三个参数,但绝大多数场景下开发者只会用到第一个甚至不用任何参数,因此TS特意做了兼容:允许源函数的形参数量少于目标类型要求的形参数量,只要剩余形参的类型匹配即可。
这不是类型系统的bug,是刻意设计的开发体验优化。
2. 无参函数的隐式类型
示例中() => '1'的隐式推导类型为() => string,它能成功赋值给类型为(p: string) => void的变量a,是因为同时满足两个兼容性规则:
- 参数层面:源函数不需要接收形参,符合「源函数形参数量可少于目标类型要求」的规则
- 返回值层面:目标类型的返回值标记为
void,TS对void类型返回值的校验规则是不限制函数实际返回值类型,仅约束调用方不能使用该返回值,因此返回string类型也不会触发报错。
补充:(p: number) => {}赋值不报错的原因
这行代码不抛错和TS的默认类型检查配置有关:未开启strictFunctionTypes配置时,TS对函数参数采用双向协变检查,允许参数类型不严格逆变的赋值;如果开启strictFunctionTypes(开启strict模式时会默认打开该配置),这行代码会直接抛出类型错误,符合严格类型校验的预期。
内容的提问来源于stack exchange,提问作者flyflydogdog
相关产品推荐
相关产品推荐

