I've hit a roadblock in my attempt to ensure type safety for a function that should take an object and return a number. Despite numerous efforts, I haven't been successful. To give you a simple example (the actual application involves more complex interfaces), consider the following:
interface Parent {
id: number;
children: Child[];
}
interface Child {
text: string;
}
const parents: Parent[] = [
{
id: 1,
children: [
{text: 'Child 1a'}, {text: 'Child 1b'},
{text: 'Child 1c'}, {text: 'Child 1d'},
{text: 'Child 1e'}
]
},
{
id: 2,
children: [
{text: 'Child 2a'}, {text: 'Child 2b'}, {text: 'Child 2c'}
]
}
];
function getMaxNumChildren<T>(data: T[], childKey: keyof T) {
return data.reduce((max: number, parent: T) => {
return max > parent[childKey].length ? max : parent[childKey].length;
}, 0);
}
console.log(getMaxNumChildren<Parent>(parents, 'children')); // 5
As expected, parent[childKey].length
throws an error since TypeScript is unaware that T[keyof T]
represents an array.
I've experimented with casting to any[]
, among other approaches, but have yet to find a solution while keeping the function fully generic. Any suggestions?