【发布时间】:2022-11-25 12:40:08
【问题描述】:
我正在寻找一个函数,该函数可以使用对象上的任何键过滤通用数组并返回唯一项。但是 Typescript 允许我将 T[Key] 用作数组而不是字典的键。
此代码有效:
const unique = <T, Key extends keyof T>(array: T[], key: Key): T[] => {
var uniqueArray: T[Key][] = []
var distinct: T[] = []
for (var i = 0; i < array.length; i++) {
if (!uniqueArray.includes(array[i][key])) {
distinct.push(array[i])
uniqueArray.push(array[i][key])
}
}
return distinct
}
export default unique
此代码不起作用:
const unique = <T, Key extends keyof T>(array: T[], key: Key): T[] => {
var uniqueDict: {[T[Key]]: number} = {}
var distinct: T[] = []
for (var i = 0; i < array.length; i++) {
if (!uniqueDict[array[i][key]]) {
distinct.push(array[i])
uniqueDict[array[i][key]] = 1
}
}
return distinct
}
export default unique
第二个代码示例在 var uniqueDict ... 行上给出了 A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.ts(1170) 的错误。
如果我把字典写成{[id: T[Key]]: number} = {},它也会在var uniqueDict ...行给出An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.ts(1337)的错误。
关于如何使独特方法的字典版本起作用有什么帮助吗?
【问题讨论】:
-
您的代码存在多个问题;我可能会将其更改为 this version,它仅使用
Record<string, number>而不是尝试将其设为{[P in T[Key]]: number}(这就是您编写该类型的方式,但除非您有重要的理由这样做,否则这是不值得的Record<string, number>)。那能满足你的需求吗?如果是这样,我可以写一个答案来解释;如果没有,我错过了什么? -
这对我有用,但是它怎么知道
array[I][key]将无限期地成为一个字符串?我想一个对象的所有键都可以假定为一个字符串,因为它们可以作为obj['key']访问?这就是为什么它起作用的原因。我是打字稿的新手,我曾尝试使用Record,但我使用的是T[Key]类型而不是string,它在那里并不开心。 -
我限制了
T extends Record<K, string>,所以编译器知道array[i](T类型)在key(K类型)处有一个属性可以分配给string。当我写下我的答案时,我会解释更多。
标签: typescript typescript-generics