Reputation: 122
How could one properly typescript the following method:
const getVars = (vars: string[]) => {
const data = [
{
"someId": "28",
"someAttr": "2",
},
{
"someId": "43",
"someOtherAttr": "3",
},
{
"someOtherId": "32",
"someAttr": "4",
}
] // an array containing some data
const result = vars.reduce((acc, _var) => ({
...acc,
...data.reduce((acc, acc) => ({
...acc,
[...acc[_var], curr[_var]]
}, {})
}), {})
return result
}
usage:
const { someId, someAttr } = getVars(['someId', 'someAttr'])
output:
someId: ['28', '43'], someAttr: ['2', '4']
I'd like to typescript getVars
so the return type would reflect given parameters, for example, if I pass ['someId'] as parameter, the typescript would know the function returns an object with key 'someId'.
Upvotes: 3
Views: 1334
Reputation: 42198
You can type this kinda-sorta strictly or very strictly. It depends on how much information you know up front (do you know the keys of the elements of data
?) and how crazy you want to be. Your data
here is an array
of object
s with string
keys. Are the values always string
? Or do they just happen to be in this example?
For the kinda-sorta strict approach, I am assuming that the values are always string
and that data
has type Record<string, string>[]
.
We want to know the specific string values that we passed to getVars
, so we will use a generic T extends string
. We return an object that has those specific strings T
as keys and the values are an array of strings. So the return type is Record<T, string[]>
.
When you are building an object through reduce()
you need to use as
to assert the type of the final object.
const getVars = <T extends string>(vars: T[]): Record<T, string[]> => {
return vars.reduce((acc, _var) => ({
...acc,
[_var]: data.map(o => o[_var]).filter(v => v !== undefined)
}), {} as Record<T, string[]>);
}
const { someId, someAttr } = getVars(['someId', 'someAttr'])
console.log(someId, someAttr);
Upvotes: 6
Reputation: 9124
const data = [
{
"someId": "28",
"someAttr": "2",
},
{
"someId": "43",
"someOtherAttr": "3",
},
{
"someOtherId": "32",
"someAttr": "4",
}
];
const getVars = (data, vars) => {
return data.reduce((acc, curr) => {
Object.keys(curr).filter(key => vars.includes(key)).forEach(
key => acc[key] = [...(acc[key] || []), curr[key]],
);
return acc;
}, {});
}
console.log(getVars(data, ['someId', 'someAttr']));
Upvotes: -1