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'.
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 objects 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);
Typescript Playground Link
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With