TypeScript在多个泛型参数上的自动推断到底是如何工作的?
我遇到这样一种情形:想要通过 extends 关键字自动推断第二个泛型的类型:
function b<T, U extends Partial<T>>(u: U) {
return u
}
b<User>({name: 'string'})
然而,当我想调用它时,编译器说我还需要再指定一个第二个泛型参数(“期望2 个类型参数,但只得到1 个”)。
然而,如果我这样写:
function b<T>() {
return function<P extends Partial<T>>(p: P) {
return p
}
}
b<User>()({name: 'string'})
它不会要求我再提供泛型参数,而是会自动推断出类型。
为什么?
解决方案
TypeScript要么自动推断一个函数的所有类型参数,要么你显式地提供全部类型参数。不存在“推断部分、再由你提供其他部分”的中间地带。
b<User>({name: 'string'}) 失败,因为当你写入 b<User>(...) 时,你进入了显式类型参数模式。TypeScript现在期望你为该函数提供每一个类型参数,它不会推断剩余的参数。由于 b 拥有两个类型参数 <T, U>,它要求两者都提供:
b<User, Partial<User>>({name: 'string'}) // works, but defeats the purpose
这是设计所致。TypeScript团队已经明确决定不在单次调用中支持部分类型参数推断,因为哪些参数会被推断、哪些需要显式提供的规则会变得模糊且难以推理清楚(参见 microsoft/TypeScript#26349)。
至于:
function b<T>() {
return function<P extends Partial<T>>(p: P) {
return p
}
}
b<User>()({name: 'string'})
当前版本之所以可用,是因为你现在分成了两次独立的函数调用,每次调用都有自己独立的推断上下文:
b<User>()- 你为外部函数显式提供了T = User。这会返回一个 new 函数,其签名现在已具体化为<P extends Partial<User>>(p: P) => P。({name: 'string'})- TypeScript会为这第二次调用从你传入的参数重新推断出P。没有显式的类型参数被提供,因此推断可以自由进行。
这两次调用从不互相竞争——它们各自要么完全显式,要么完全自动推断。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。