Typescript 泛型数组上的映射推断出错误的类型
在下面的示例中,我注意到了意外的交互。当我尝试将映射到通用的选项时,里面的项目不是我所期望的类型Typescript 泛型数组上的映射推断出错误的类型,typescript,generics,Typescript,Generics,在下面的示例中,我注意到了意外的交互。当我尝试将映射到通用的选项时,里面的项目不是我所期望的类型 const foo = <T extends string[]>(options: T, labels: Record<T[number], string>): string[] => { return options.map(o => labels[o]); } 为string数组项创建类型参数T,而不是为数组创建类型参数: const foo=( 选
const foo = <T extends string[]>(options: T, labels: Record<T[number], string>): string[] => {
return options.map(o => labels[o]);
}
为
string
数组项创建类型参数T
,而不是为数组创建类型参数:
const foo=(
选项:T[],标签:记录):字符串[]=>{
返回options.map(o=>labels[o]);
}
foo([“A”,“B”]作为[“A”,“B”]{
A:“标签A”,
B:“标签B0”,
})
这是因为映射类型不正确,还是这是预期的行为
预计标签[o]处会出现错误。在您的示例中,标签
是一种记录
类型,因此您可以使用类型为T[number]
的键对其进行索引
现在,当您在选项
上调用映射
时,TS将使用T
(string[]
)的基本约束来推断项目类型string
——这是常见基本类型的最佳选择,我们在这里可以看到。而且string
不能分配给T[number]
,因此您在这里得到一个错误
通过使用固定键,我们可以确保记录键和数组项的类型相同。
o
是一个string
,因为您将T定义为string[]
。如果希望o
是一个数字,那么它应该是T,因为number[]
T
不是字符串[]
,它只是扩展了它。示例中的任何内容都与数字无关。“但是,map函数表示它的o控制变量的类型为string。”---如果没有字符串,您希望看到什么?T[number]
类型更具体。当f.e.I将泛型设置为T扩展[“A”,“B”]
时,o
被推断为“A”|“B”
。既然像这样的字符串文字数组扩展了字符串数组,那么映射函数不应该期望这样的用例,而不仅仅是将string
放在那里吗?您没有解释t[number]
工作不正确的原因,据我所知,这是问题的核心。添加第二个K
参数感觉像是写了一些不必要的东西,但我现在明白了为什么会出现这个问题。我仍然觉得它没有发挥应有的作用,但TS就是这样工作的。@MarošBeťko如果你声明
,很难说出T
的实际项目类型是什么,也很难将该类型与T[number]
匹配。通过仅为项类型声明类型参数并完全忽略数组类型,可以进一步简化示例。对于您的示例来说,这应该足够了,请查看编辑后的答案。干杯
foo(["A", "B"] as ["A", "B"], {
A: "Label A",
B: "Label B",
})
const foo = <T extends string>(
options: T[], labels: Record<T, string>): string[] => {
return options.map(o => labels[o]);
}
foo(["A", "B"] as ["A", "B"], {
A: "Label A",
B: "Label B0",
})