I have an interface, greatly simplified for brevity:
interface Author {
id?: number;
firstName?: string;
lastname?: string;
age?: number;
coAuthors?:
[
{
id: number;
firstName: string;
lastname: string;
age: number;
}
]
}
Trying here to get an object value by key:
const getByKeyName = <T extends {coAuthors: ['coAuthors']}, K extends keyof T>(item: T, key: K) =>
{
return item[key] ?? (item.coAuthors?.length ? item.coAuthors![0][key] : 0);
}; ^^^^^^^^^
cannot use [key] to index item.coAuthors![0]
-----------------------------
getByKeyName(author, 'id');
This results in the TS error above, because child is a different object. What’s best to implement that?
TypeScript doesn’t know that the key exists in both the main object and its child objects within the coAuthors array.
interface Author {
id?: number;
firstName?: string;
lastname?: string;
age?: number;
coAuthors?: {
id: number;
firstName: string;
lastname: string;
age: number;
}[];
}
const getByKeyName = <T extends Author, K extends keyof T | keyof T['coAuthors'][0]>(
item: T,
key: K
) => {
if (key in item) {
return item[key as keyof T];
} else if (item.coAuthors && item.coAuthors.length > 0 && key in item.coAuthors[0]) {
return item.coAuthors[0][key as keyof T['coAuthors'][0]];
}
return 0;
};
// Usage example:
const author: Author = {
id: 1,
firstName: "John",
lastname: "Doe",
age: 50,
coAuthors: [
{
id: 2,
firstName: "Jane",
lastname: "Smith",
age: 40
}
]
};
console.log(getByKeyName(author, 'id')); console.log(getByKeyName(author, 'firstName'));
The key type K now extends keyof T | keyof T[‘coAuthors’][0], making it possible to check the key within both the main object and the coAuthors array.