Typescript parameters - a generic array of objects and array of object's keys (partial)

浪子不回头ぞ 提交于 2021-02-08 03:47:37

问题


I want to have a method that accepts an array of objects and an array of some of the objects keys. The method will return an array of arrays of object values but only of the selected keys.

data:

[
  {"firstName": "Jane", "lastName": "Doe"},
  {"firstName": "John", "lastName": "Doe"}
]

fields:

["firstName"]

result:

[["Jane"], ["John"]]

By now I have a function that provides desired outcome but I am not sure how to handle the types better.

mapToCsvData: (data: { [key: string]: any }[], fields: string[]) => {
  return data.map((item: any) => {
    return fields.map(field => item[field]);
  });
}

I have tried some variations of the next snippet but I get an error.

mapToCsvData: <T extends object>(data: T[], fields: keyof T[]) => {
Property 'map' does not exist on type 'number'.

回答1:


You will need an extra type parameter to capture the actual tuple of keys being passed in. You can them map this tuple to the corresponding property types in T. It all works out very nicely:

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]


来源:https://stackoverflow.com/questions/56342559/typescript-parameters-a-generic-array-of-objects-and-array-of-objects-keys-p

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!