TypeScript类型推断不符合预期:相似函数表现差异问题
TypeScript泛型函数类型推断差异问题解析
我定义了两个结构相似的TypeScript函数,但TypeScript仅能正确推断其中一个的返回值:
interface URItoKind<A> {} type URIS = keyof URItoKind<any>; type Kind<URI extends URIS, A> = URItoKind<A>[URI]; const URI = "Option"; export type URI = typeof URI; interface URItoKind<A> { readonly [URI]: Option<A>; } class Option<A> { static of: <A>(a: A) => Option<A>; } function test1<F extends URIS, A, B>(f: (a: A) => Kind<F, B>): Option<B>; function test2<F extends URIS>(): <A, B>(f: (a: A) => Kind<F, B>) => Option<B>; const func = (x: number) => Option.of(x.toString()); // (x: number) => Option<string> const r1 = test1(func); // Option<unknown> - 无法正常推断 const r2 = test2()(func); // Option<string> - 推断正常
现象原因
- TypeScript的泛型类型推断是按参数顺序进行的。
test1的泛型参数<F extends URIS, A, B>需要同时从输入参数f中推断,但Kind<F, B>的嵌套结构导致TypeScript无法同时反向推导出F和B——它优先绑定F为URI(对应Option类型),但无法进一步从(a: A) => Kind<F, B>中准确提取B的具体类型,最终只能将B推断为unknown。 test2是柯里化后的函数:先隐式推断出F的类型,返回的新函数仅需推断A和B。此时TypeScript可以直接从func的返回值Option<string>中提取B = string,推断流程无多泛型参数的冲突,因此结果正确。
是否属于预期行为
这是TypeScript的预期行为,并非Bug。TypeScript的泛型推断能力受限于参数的依赖关系和推断顺序,当多个泛型参数共享同一输入源且存在间接依赖时,推断逻辑会出现模糊性,无法覆盖所有复杂场景。
无需手动指定类型的修复方案
可以通过调整泛型参数的约束顺序,或利用条件类型明确推导路径,让TypeScript优先推断B的类型:
// 方案1:调整泛型参数顺序,让B的推断优先级更高 function test1<F extends URIS, B, A>(f: (a: A) => Kind<F, B>): Option<B>; // 方案2:利用infer提取返回值中的B类型,更严谨 function test1<F extends URIS, T extends (a: any) => Kind<F, any>>(f: T): Option<T extends (a: any) => Kind<F, infer B> ? B : never>;
调整后调用test1(func)即可正确推断出返回值为Option<string>。
内容的提问来源于stack exchange,提问作者danik
相关产品推荐
相关产品推荐

