TypeScript参数 - 一个对象数组和对象键的通用数组(部分)

4
我想要一个方法,接受一个对象数组和一个包含部分对象键的数组。该方法将返回一个只包含选定键的对象值的二维数组。
数据为:
[
  {"firstName": "Jane", "lastName": "Doe"},
  {"firstName": "John", "lastName": "Doe"}
]

领域:
["firstName"]

结果:
[["Jane"], ["John"]]

到目前为止,我有一个能提供所需结果的函数,但我不确定如何更好地处理类型。
mapToCsvData: (data: { [key: string]: any }[], fields: string[]) => {
  return data.map((item: any) => {
    return fields.map(field => item[field]);
  });
}

我尝试了下一个片段的一些变化,但是出现了错误。
mapToCsvData: <T extends object>(data: T[], fields: keyof T[]) => {

Property 'map' does not exist on type 'number'.
1个回答

5
您需要一个额外的类型参数来捕获传入的实际键元组。然后,您可以将此元组映射到T中相应的属性类型。所有这些都非常完美。
type MapKeyTupleToProps<T, P extends [keyof T] | Array<keyof T>> = {
    [K in keyof P]: P[K] extends keyof T ? T[P[K]] : never
}
const m = {
    mapToCsvData: <T, P extends [keyof T] | Array<keyof T>>(data: T[], fields: P): MapKeyTupleToProps<T, P> => {
        return data.map((item: any) => {
            return fields.map(field => item[field]);
        }) as any;
    }
}

const data = [
    {"firstName": "Jane", "lastName": "Doe", age: 0},
    {"firstName": "John", "lastName": "Doe", age: 0}
]

let r = m.mapToCsvData(data, ["firstName", "lastName"]) // [string, string]
let r2 = m.mapToCsvData(data, ["firstName", "age"]) //[string, number]

谢谢。这真的很奇怪,但当我将 MapKeyTupleToProps 移动到我的带有类型的主文件中时,MapKeyTupleToProps<T, P> 中的 P 会出现错误“类型 '[keyof T]' 不可分配给类型 'flat'”。 - CrossTheDev
@CrossTheDev 不确定为什么会发生这种情况..它应该可以工作..我相信从3.1开始支持这种类型的映射元组。 - Titian Cernicova-Dragomir
我目前使用的是3.4.1版本,所以这不应该是一个问题。 - CrossTheDev
我找到了关于“P”错误消息背后的问题。原来我的代码检查器更喜欢使用[]而不是Array,所以我将“Array<keyof T>>”改为“keyof T[]”,但正确的变体应该是“(keyof T)[]”。这是我的失误。 - CrossTheDev
@CrossTheDev 是的..如果项目类型不止一个单词,我更喜欢使用Array,这样更容易阅读。对于(keyof T)[],你需要加上(),而且很容易忽略末尾的[]。不过我相信这个lint规则是可以配置的。 - Titian Cernicova-Dragomir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接