Home > Software design >  How to return a nested type of a type that was passed in
How to return a nested type of a type that was passed in

Time:02-20

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.

Typescript Playground

CodePudding user response:

Actually, in my playground your solutions works: TypeScript Playground [updated]

  • Related