TypeScript:如何编写符合函数类型交集的函数?
为什么TypeScript交叉函数类型的实现会报错?
首先得明确TypeScript对函数交叉类型的校验逻辑:当你把一个函数赋值给((x: number) => boolean) & ((y: string) => bigint)这种交叉类型时,TypeScript要求这个函数必须同时满足两个分支的调用要求——也就是说:
- 传入
number类型参数时,必须返回boolean; - 传入
string类型参数时,必须返回bigint。
你的错误代码里,虽然用了类型守卫,但TypeScript做类型赋值校验时,是把函数的整体输入输出类型和交叉类型的每个分支做匹配:
- 你的函数输入是
number | string,输出是bigint | boolean; - 当检查它是否符合
(x: number) => boolean时,TypeScript发现函数的返回类型是联合类型,无法保证一定返回boolean(静态类型检查不会深入到条件分支的逻辑判断),因此抛出错误。
正确的实现方式
方法1:使用函数重载(推荐)
函数重载的签名可以完美匹配交叉类型的分支要求,TypeScript会认可这种实现:
type InterFunc = ((x: number) => boolean) & ((y: string) => bigint); // 定义重载签名 function myFunc(a: number): boolean; function myFunc(a: string): bigint; // 实现函数本体 function myFunc(a: number | string): boolean | bigint { if (typeof a === 'number') return true; return BigInt(a.length); } // 可以正常赋值给交叉类型 const func: InterFunc = myFunc;
方法2:使用类型断言(谨慎使用)
如果你能确定函数逻辑完全正确,可以用类型断言跳过TypeScript的静态检查:
type InterFunc = ((x: number) => boolean) & ((y: string) => bigint); let myFunc: InterFunc = ((a: number | string) => { if (typeof a === 'number') return true; return BigInt(a.length); }) as InterFunc;
总结
TypeScript对函数交叉类型的校验是基于函数的整体类型签名,而非分支逻辑。函数重载通过明确的多签名定义,让TypeScript识别出不同输入对应的不同输出,因此可以完美匹配交叉类型;而类型断言则是强制跳过检查,适合你能确保逻辑正确性的场景。
内容的提问来源于stack exchange,提问作者Glen Whitney
相关产品推荐
相关产品推荐

