Say I have a type Person
with their name, age, and a list of all their friends.
type Person = {
name: string;
age: number;
friends: Person[];
}
Then say I have a function getFriendsWithSameAge
. This function only needs the age prop in order to do what it needs to do. So instead of taking as a parameter Person
it takes a MinimalPerson
ie:
type MinimalPerson = {
age: number;
friends: MinimalPerson[];
}
export function getFriendsWithSameAge(person: MinimalPerson) {
return person.friends.filter(friend => friend.age === person.age);
}
This is nice because getFriendsWithSameAge
is very flexible in terms of input arguments. You can pass in any sort of Person object as long as it has at the very least age
and friends
defined. This is a very common scenario when using GraphQl.
The issue comes with the return type. This code complains:
const person: Person = { name: 'John', age: 32, friends: [...] }
const friend = getFriendsWithSameAge(person)[0];
const name = friend.name; // error, function call destroys typing, doesn't know what name is
I was hoping I could solve this with generics by preserving the types that were passed in and then returning them like:
export function getFriendsWithSameAge<T extends MinimalPerson>(person T): T['friends'] { // obviously doesn't work
return person.friends.filter(friend => friend.age === person.age);
}
but I can't seem to figure out how to type the return type.
edit: My attempted solution above works just fine. My issue was that T['friends']
does not work if T is nullable which is a detail I left out for the sake of this question.
CodePudding user response:
Actually, in my playground your solutions works: TypeScript Playground [updated]