仅指定单个泛型参数时,如何让后续泛型参数自动推导?
问题:指定部分泛型参数时自动推导剩余泛型
在TypeScript中定义了如下代码:
interface Option<T> { on: (p: T) => T } function identity<A, B = any> (a: A, b: B, c?: Option<B>) {} // 不指定泛型时,p能正确推导为{a: 1} identity(1, { a: 1 }, { on: p => p } ) // 仅指定泛型A时,p被推导为any identity<number>(1, { a: 1 }, { on: p => p } )
请问当仅指定泛型A时,有没有办法让泛型B根据传入的参数b自动推导?我自己想到了一个柯里化的方案,但侵入性较强:
function identity<A> (a: A) { return <B>(b: B, c?: Option<B>) => {} } identity<number>(1)({ a: 1 }, { on: p => p })
解答
这是因为TypeScript的泛型推断规则:当你显式指定了部分泛型参数时,剩余未指定的参数会直接使用它们的默认值(这里B的默认值是any),不会再从函数参数里自动推导。下面提供几种可行的解决方法:
1. 柯里化拆分(你的方案)
把函数拆分成两次调用,第一次指定A并接收参数a,第二次让TypeScript自动推导B。这种方式虽然改变了调用方式,但逻辑清晰,是处理部分泛型推导的常用手段,尤其在TS版本较低时很实用。
2. TypeScript 4.7+ 部分泛型参数推断
从TypeScript 4.7开始,支持用_作为泛型参数的占位符,告诉编译器“这个参数帮我自动推导”,完全不需要修改原函数结构:
identity<number, _>(1, { a: 1 }, { on: p => p // 此时p能正确推导为{a: 1} } )
这个方案侵入性最低,直接在调用时用_代替需要自动推导的泛型参数即可。
3. 调整泛型默认值(兜底方案)
如果无法升级TS版本,也可以修改函数的泛型默认值,让B的默认值从参数b的类型推断,写法稍复杂但能兼容旧版本:
type InferFromArg<T> = T extends undefined ? any : T function identity<A, B = InferFromArg<typeof b>>(a: A, b: B, c?: Option<B>) {}
不过这种方式不如前两种直观,优先级低于前两个方案。
内容的提问来源于stack exchange,提问作者beginner
相关产品推荐
相关产品推荐

