Gaurav Saluja
Gaurav Saluja

Reputation: 713

Typescript function extended interface type

I have a function which takes an array of objects which do not have an id property and return all those objects with an id property added to them.

const pickIdAndDocs = (arr) => {
  return arr.map(doc => ({
    id: 1,
    ...doc
  }))
}

Now, for example if i have this interface

interface iUser {
  name: string;
}

and an array containing values of type iUser

let users: iUser[] = [ {name: "John"}, {name: "Joe"} ];

How do i specify the return type of the function pickIdAndDocs, such that it returns an array where each item is an extended type of the input type it takes with an added id property

function pickIdAndDocs<T>(items : T[] ) : extendedT[];

This function can take an array of any type (will always be objects/key-value pairs), an return all items with an appended id property.

Or am i approaching this the wrong way? Thanks :)

Upvotes: 1

Views: 137

Answers (1)

Nishant
Nishant

Reputation: 55866

Essentially we want to build up new type by combining two types. One with {id: number} and another is whatever passed to the function. This exactly what intersection type does. Assuming my interpretation of your problem is correct, I think this is what you want:

interface User {
  name: string;
}

type WithId<T> = T & { id: number };

const pickIdAndDocs = <T,>(arr: T[]): WithId<T>[] => {
  return arr.map((doc) => ({
    id: 1,
    ...doc,
  }));
};

let users: User[] = [{ name: "John" }, { name: "Joe" }];

const usersWithId = pickIdAndDocs(users);

// No warning!
usersWithId[0].id;
usersWithId[0].name;

// Warning: Property 'age' does not exist on type 'WithId<User>'.
usersWithId[0].age;

Here is the TS Playground link: https://tsplay.dev/ND5B4m

Upvotes: 4

Related Questions