在尝试创建地图时,我收到一个我不太明白的奇怪错误:
TS2769: No overload matches this call.
Overload 1 of 4, '(iterable: Iterable<readonly [string, number]>): Map<string, number>', gave the following error.
Argument of type '(string | number)[][]' is not assignable to parameter of type 'Iterable<readonly [string, number]>'.
The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
Type 'IteratorResult<(string | number)[], any>' is not assignable to type 'IteratorResult<readonly [string, number], any>'.
在我的代码中,我接受了一个数组并尝试构造它的映射对象
function createMapOfHeadersToIndex(headers: string[]): Map<string, number> {
const headersWithIndex =
headers.map(header => [header, Number(headers.indexOf(header))]);
return new Map(headersWithIndex);
}
答案 0 :(得分:1)
由于您没有 annotate 的类型 headersWithIndex
,编译器根据人们倾向于使用数组的启发式规则为您推断它的类型:
const headersWithIndex =
headers.map(header => [header, Number(headers.indexOf(header))]);
// const headersWithIndex: (string | number)[][]
该类型,(string | number)[][]
表示“由 string
或 number
元素组成的数组”。这并不是对 headersWithIndex
的错误描述,在其他情况下,您可以合理猜测您可能会用它做什么:
headersWithIndex.push([1, "two", 3, "four"]); // okay
不幸的是,该类型不够具体,无法被 Map
构造函数接受,该构造函数期望一个可迭代对象,其元素显式为键的 2-{{3}} 后跟一个值。因此构造调用失败,因为编译器忘记了有关 headersWithIndex
元素内数组的特定顺序和长度的任何信息。
解决此问题的最直接方法是在创建包含键和值的数组文字时使用 tuple:
const headersWithIndex =
headers.map(header => [header, Number(headers.indexOf(header))] as const);
// const headersWithIndex: (readonly [string, number])[]
return new Map(headersWithIndex); //okay
那个 as const
给编译器一个提示,你希望它推断出它所能推断的最具体的类型;这几乎就像在说“我不会改变这个东西的内容,所以请注意一切的确切位置”。你会看到现在 headersWithIndex
被推断为类型 (readonly [string, number])[]
;也就是说,由一个 string
和一个 number
组成的 const
assertion 数组。
现在 Map
构造函数很高兴,因为它肯定知道 headersWithIndex
的每个元素都是一对 string
键和 number
值,结果在 Map<string, number>
中。