TypeScript实现多调用签名函数时返回类型不匹配如何解决?
报错原因
TypeScript 在校验「重载类型的函数实现」时,不会深入推导函数内部的分支逻辑和入参、返回值的对应关系,只会拿你整个实现的返回值联合类型,逐一和每个重载的返回类型做匹配校验。
你当前的实现整体返回值类型是 "umbrella_foo" | "shorts_foo" | "anything",TS 匹配第一个重载 (option: 'rain'): umbrella_${string}时,会要求返回值联合类型的所有成员都符合 umbrella_${string} `` 的约束,显然 "shorts_foo" 不满足这个约束,就抛出了你看到的报错。
解决方法
下面给出三种常用的可行方案:
方案1:改用函数声明式重载写法(最推荐)
TS 对函数声明式重载的校验逻辑更贴合实际使用场景,不会出现上述误判:
type Options = "rain" | "sun" | "wind" | "snow"; function myFunctionFoo(option: 'rain'): `umbrella_${string}`; function myFunctionFoo(option: 'sun'): `shorts_${string}`; function myFunctionFoo(option: Options): string; function myFunctionFoo(options: Options) { if (options === "rain") { return 'umbrella_foo'; } if (options === "sun") { return 'shorts_foo'; } return 'anything' }
方案2:给箭头函数加类型断言
如果你一定要用箭头函数+重载类型别名的写法,可以给整体函数加类型断言跳过严格校验,只要你确认自己的分支逻辑符合重载要求即可:
type Options = "rain" | "sun" | "wind" | "snow"; type OverloadedFunction = { (option: 'rain'): `umbrella_${string}`; (option: 'sun'): `shorts_${string}`; (option: Options): string; }; const myFunctionFoo: OverloadedFunction = ((options: Options) => { if (options === "rain") { return 'umbrella_foo'; } if (options === "sun") { return 'shorts_foo'; } return 'anything' }) as OverloadedFunction;
方案3:泛型+条件类型替代重载
如果你不想用重载,也可以用泛型搭配条件类型实现同样的类型约束:
type Options = "rain" | "sun" | "wind" | "snow"; type ReturnMap<T extends Options> = T extends 'rain' ? `umbrella_${string}` : T extends 'sun' ? `shorts_${string}` : string; const myFunctionFoo = <T extends Options>(option: T): ReturnMap<T> => { if (option === "rain") { return 'umbrella_foo' as ReturnMap<T>; } if (option === "sun") { return 'shorts_foo' as ReturnMap<T>; } return 'anything' as ReturnMap<T>; }
内容的提问来源于stack exchange,提问作者Andru
相关产品推荐
相关产品推荐

