typescript 未按预期从泛型类推断类型脚本类型参数

zqry0prt  于 2023-02-05  发布在  TypeScript
关注(0)|答案(1)|浏览(105)

在本例中,我使用参数类型(keyof TFoo)[]来预期包含TFoo中的任何键的数组,为了使示例简单,但是我在任何时候使用模式<T, TSomeClass extends SomeClass<T>>时都看到了类型参数的推断的相同行为。它似乎正确地推断了类型TFoo,因为它适用于第一个fooBarBad函数参数bar的类,所以在这个例子中,它将TBar标识为Bar<{ a: number, b: number }>,但是对于第二个参数fooKeys,它将TFoo推断为{ a: any, c: any },这是从数组中传递的值中获得的。但我至少希望它对两个函数参数应用相同的TFoo推断值,因为它们都引用相同的类型参数TFoo

class Bar<TFoo> {
  constructor(foo: TFoo) {}
}

function fooBarBad<TFoo, TBar extends Bar<TFoo>>(bar: TBar, fooKeys: (keyof TFoo)[]) {}

// No error, but I expect one - fooKeys is instead inferred to be ('a' | 'c')[]
fooBarBad(new Bar({ a: 1, b: 2 }), ['a', 'c']);

有没有别的方法可以声明这个来得到我想要的推论?或者有什么技巧来强迫它?
一个更简单的例子就能得出我所期望的结论。

function fooBar<TFoo>(foo: TFoo, fooKeys: (keyof TFoo)[]) {}

// Error as expected - 'c' is not a key of TFoo
fooBar({ a: 1, b: 2 }, ['a', 'c']);

b4lqfgs4

b4lqfgs41#

TypeScript在查找推理目标时会确定参数的优先级。TBar的类型由第一个参数推理,而TFoo由第二个参数推理,* 而不是 * 通过TFoo的约束推理。
我们可以简化您的示例,只使用一个泛型参数TFoo

class Bar<TFoo> {
  constructor(foo: TFoo) {}
}

function fooBarBad<TFoo>(bar: Bar<TFoo>, fooKeys: (keyof TFoo)[]) {}

从而得出正确的推论。

fooBarBad(
  new Bar({ a: 1, b: 2 }), ['a', 'c']
//                               ~~~ Type '"c"' is not assignable
//                                   to type '"a" | "b"'
)

Playground

相关问题