You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:42:41