我正在尝试编写类型级别函数Foo
,该函数将获取“二维”数组的第一个元素的类型。我写了以下
type Foo<A extends any[][]> = {
[I in keyof A]: First<A[I]>
}
type First<A extends any[]> = A[0]
此代码无法编译并出现以下错误
Type 'A[I]' does not satisfy the constraint 'any[]'.
Type 'A[keyof A]' is not assignable to type 'any[]'.
Type 'A[string] | A[number] | A[symbol]' is not assignable to type 'any[]'.
Type 'A[string]' is not assignable to type 'any[]'.
我正在努力理解。具体来说,A[string] | A[number] | A[symbol]
的来源。据我了解,mapped arrays应该允许我索引应该是更多数组的数组元素。我可以通过定义First
来解决条件类型的问题
type First<A> =
A extends any[] ? A[0] :
never;
但我不明白为什么这样做是必要的。
答案 0 :(得分:2)
我知道这很令人讨厌。它被标记为bug。根本问题seems to be是编译器仅在您使用所映射的类型时才意识到它是在映射数组/元组,而不是在您定义时对其进行映射。
// here the compiler doesn't know that I will be a numeric-like key:
type Foo<A extends any[][]> = { [I in keyof A]: Extract<A[I], any[]>[0] };
// only here does the compiler perform the mapping with just the numeric-like keys:
type Expected = Foo<[[1, 2], [3, 4], [5, 6], [7, 8]]>;
// type Expected = [1, 3, 5, 7]
还可以使编译器将数组类型映射为纯对象,包括诸如length
,join
等非数字键:>
type Unexpected = Foo<[[1, 2], [3, 4], [5, 6], [7, 8]] & { a: string }>;
/* type Unexpected = {
[x: number]: 1 | 3 | 5 | 7;
0: 1;
1: 3;
2: 5;
3: 7;
length: never;
toString: never;
toLocaleString: never;
pop: never;
push: never;
concat: never;
join: never;
reverse: never;
shift: never;
slice: never;
sort: never;
... 18 more ...;
a: never;
}
*/
这甚至是可能的事实意味着编译器无法假设A[I]
可分配给any[]
,因此您目前不得不做类似Extract<A[I], any[]>
的事情(类似于您的修复程序。)
希望有所帮助;祝你好运!