我正在创建一个包装器来处理 Typescript 中的 NextJS API 请求。但是,当我想为函数中的泛型类型之一传递单一类型时,出现类型错误。
我创建了一个简单的函数来显示此错误。下面的示例传递 2 个参数并将参数 bar
更改为数组。除非明确定义,否则foo
的类型应该是unknown
。 bar
的类型应该始终被推断。当未显式定义泛型类型时,会正确推断函数的返回类型(第 6 行)。
但是,当泛型类型 Foo
设置为 number 时,会出现类型错误,因为类型 Bar
会自动设置为未定义,并且不再从参数的类型推断出来(第 9 行)。
第 12 行显示了如果您想定义至少其中 1 个泛型类型,则如何强制定义所有泛型类型。
function test<Foo = unknown, Bar = undefined>(foo: Foo, bar: Bar) {
return { foo, bar: [bar] }
}
// Works - Return type { foo: number; bar: string[] }
const a = test(10, 'bar')
// Does not work - Return type { foo: number; bar: undefined[] }
const b = test<number>(10, 'bar')
// Works - Return type { foo: number; bar: string[] }
const c = test<number, string>(10, 'bar')
是否有一种解决方法可以选择定义泛型类型而不手动定义其他类型?
最佳答案
TypeScript 目前不直接支持部分 generic类型参数推理。如果您有一个具有多个类型参数的泛型函数,例如 declare function foo<T, U>(t: T, u: U): F<T, U>;
那么您可以手动指定所有这些,例如 foo<X, Y>(x, y)
,或者您可以让编译器推断所有这些,如 foo(x, y)
。您无法指定某些内容,但可以推断其他内容,如 foo<X>(x, y)
中所示。 。请参阅microsoft/TypeScript#26242相关功能请求。
不,generic parameter defaults喜欢 declare function foo<T = A, U = B>(t: T, u: U): F<T, U>
不要为您提供此功能。如果有默认值,则指定某些参数将为您留下的参数提供默认值。它不推断任何东西。也许将来会有像declare function foo<T = infer, U = infer>(t: T, u: T): F<T, U>
这样的语法。它允许将默认值压入服务中以进行部分类型参数推断。但就目前而言,它还不是语言的一部分。
除非实现 microsoft/TypeScript#26242,否则有解决方法。我最常用的是 currying 。由于每个泛型函数调用都要求您指定所有类型参数或推断所有类型参数,因此您可以通过将单个函数调用拆分为多个来模拟部分推断。所以你可以做const fooCurry: <T,>(t: T): <U,>(u: U) => F<T, U>
或类似的。
对于您的示例代码,它看起来像:
const testCurry = <F,>(foo: F) => <B,>(bar: B) => test(foo, bar);
然后调用变成
const b = testCurry<number>(10)('bar');
/* const b: { foo: number; bar: string[]; } */
您成功指定 F
的地方是 number
但让编译器推断 B
是 string
.
关于typescript - 未推断可选泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74599925/