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

为什么这段代码能让TypeScript从父函数推断泛型类型?

TypeScript 泛型上下文推导特性解答

特性本质

你提到的「子函数泛型从父函数参数反推」是TypeScript有意设计的标准特性,属于「上下文类型(Contextual Typing)」推导规则的一部分,并不是未定义的野特性。
TypeScript的泛型推导不是单向的,除了从函数实参往返回值推导之外,当一个值的类型被它所处的上下文环境(比如父函数的参数类型要求)明确约束时,会反向推导该值内部的未确定泛型参数。

两个示例的差异原理

你给出的两个update函数表现不同,核心差异在于泛型T的推导时机:

不生效的版本

function update<T>(u: Partial<T>) { return (t: T) => ({ ...t, ...u }) }

当你调用update({ foo: 1 })时,TypeScript会优先从实参推导泛型:参数u的类型是Partial<T>,传入的实参是{ foo: 1 },这时候T会直接被推导为{ foo: number },后续你把返回的函数传给apply<Model>时,类型已经固定为(t: {foo: number}) => {foo: number},和apply要求的(t: Model) => Model不匹配,自然会报错。

生效的版本

function update<T>(u: T extends infer U ? Partial<U> : never) { return (t: T) => ({ ...t, ...u }) };

这里用到的T extends infer U ? Partial<U> : never属于延迟解析的条件类型:只要条件类型中存在未确定的泛型参数,TypeScript就不会提前解析这个类型的具体形态。
所以当你调用update({ foo: 1 })时,TS无法从参数u的类型反推T的具体值,只能暂时挂起T的推导。这时候你把返回值传给apply<Model>,apply明确要求传入的函数类型是(t: Model) => Model,和update返回的(t: T) => T匹配时,就会反向推导出T必须是Model。确定T的类型后,TS再回头校验你传入的{ foo: 1 }是否符合Partial<Model>,校验通过自然不会报错。

是否为有意设计

这个特性是TypeScript类型系统的核心设计之一,上下文类型反向推导的逻辑广泛应用在事件回调、JSX属性、泛型函数传参等场景中,你用到的「延迟条件类型阻塞提前推导」也是官方支持的泛型技巧,常用于需要让泛型优先从上下文推导、而非从实参推导的场景。

内容的提问来源于stack exchange,提问作者David Shortman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:57:00