这可能是一个重复的问题。但是我似乎找不到答案,因此,如果已经回答,请随时将我指向某个地方。
使用泛型时,我发现 typescript 会根据我是否包装用作数组成员的泛型来推断出不同的类型。例如,
// Set up
type Wrapped<I> = { _i: I };
// Not working example
function foo1<TInner extends unknown>(bar: Wrapped<TInner>[]) {
return bar;
}
const a = foo1([{ _i: 5 }, { _i: "six" }]); // TInner = number, compiler complains about second array member despite the fact that it's inferring it
// Working example
function foo2<TInner extends Wrapped<unknown>>(bar: TInner[]) {
return bar;
}
const b = foo2([{ _i: 5 }, { _i: "six" }]); // TInner = Wrapped<number> | Wrapped<string>
为什么会这样呢?我缺少的文档中有东西吗?更笼统地说,有人能给我一个很好的解释,说明 typescript 如何推论泛型吗? 最佳答案
仔细研究一下代码的编写方式。
// Slightly edited given example
type Wrapped<I> = { _i: I };
function foo<T extends unknown>(baz: Wrapped<T>[]) {}
foo1([ { _i: 5 }, { _i: "six" } ]);
function bar<T extends Wrapped<unknown>>(baz: T[]) {}
foo2([ { _i: 5 }, { _i: "six" } ]);
定义foo
的通用参数T extends unknown
的方式意味着T
可以是任何东西,由unknown
表示,但它是 1 。实际函数的参数为
Wrapped<T>[]
;分解它,foo
接受一个Wrapped<T>
数组,这意味着它接受一个Wrapped
对象的列表,但是每个对象必须具有相同的类型,因此它可以接受[ { _i: 1 }, { _i: 2 }, { _i: 3 } ]
或[ { _i: 'a' }, { _i: 'b' }, { _i: 'c' } ]
,但是不能创建并集/元组因为它是输出,所以类似[ { _i: 'a' }, { _i: 2 }, { _i: Symbol(NaN) } ]
的操作将失败,因为此类型实际上是Wrapped<string | number | symbol>[]
,而前两个分别是Wrapped<number>[]
和Wrapped<string>[]
。另一方面,
bar
定义为<T extends Wrapped<unknown>>
。在这种情况下,T
只是Wrapped
类型的对象,无需关心其type参数是什么,只要它具有Wrapped
对象的一般形状即可。在这里,无论它们是否都是相同类型,它都可以采用
Wrapped
对象的数组。总结起来,
foo
接受相同类型的连续数组,而bar
接受任何Wrapped
对象的数组。关于javascript - 如果包装数组成员, typescript 泛型为什么会推断出不同的类型?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64703988/