TypeScript组合函数中条件返回类型失效问题及解决方法
TypeScript compose函数中条件返回类型失效的原因及解决办法
问题原因
你的compose函数存在两个核心问题导致条件返回类型失效:
- 重载定义无法追踪泛型关联性:
b是一个依赖泛型B来决定返回类型的高阶函数,但原compose的重载仅将参数函数视为普通的(input: X) => Y类型,无法识别Y与输入参数中B的条件关联,类型推导链在这里断裂。 - 实现层的
any抹除类型信息:compose的实现里用any处理输入和返回值,直接让TypeScript放弃了所有类型推导,自然无法识别b函数的条件返回类型。
解决办法
需要重新定义compose的类型系统,用递归泛型追踪每个函数的输入输出关联,同时避免any破坏类型推导。以下是修复后的代码:
// 递归推导组合函数的完整类型链 type Compose<T extends Array<(...args: any[]) => any>> = T extends [(x: infer X) => infer Y, ...infer Rest] ? Rest extends Array<(...args: any[]) => any> ? (x: X) => Compose<Rest> extends (y: Y) => infer Z ? Z : never : (x: X) => Y : never; export function compose<T extends Array<(...args: any[]) => any>>( ...fns: T ): Compose<T> { return (input: any) => fns.reduce((acc, fn) => fn(acc), input) as Compose<T>; } ///////////////////////// const a = <I, O>(fn: (args: I) => O) => (args: I & {a: number}): O & {a: number} => { return {...fn(args as I), a: 1}; }; const b = <I, O>(fn: (args: I) => O) => <B extends boolean>(args: I & {b: B}): B extends true ? O & {b: number} : O => { if (!args.b) { return fn(args); } return {...fn(args), b: 1} as B extends true ? O & {b: number} : O; }; const fn = (arg: {x: number}) => arg; // 现在可正确推断b属性存在,类型为number compose(b, a)(fn)({x: 1, a: 1, b: true}).b;
关键修改说明
- 递归泛型
Compose:通过递归逐步推导每个函数的输入输出类型,确保前一个函数的输出能正确匹配后一个函数的输入,同时保留高阶函数的泛型参数关联性,让b的条件类型能被正确识别。 - 移除不安全的
any断言:将实现中的as any替换为as Compose<T>,让TypeScript基于定义好的类型链完成推导,而非直接抹除类型信息。 - 优化
b函数的返回断言:替换原有的as any为精准的条件类型断言,进一步强化类型推导的准确性。
内容的提问来源于stack exchange,提问作者NirG
相关产品推荐
相关产品推荐

