问题
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