Home > Blockchain >  How to select the type of an object from an array typescript
How to select the type of an object from an array typescript

Time:10-09

I have a generated type like this : (I can't manipulate it)

type Users = Array<
| {
  typename: "personal";
  firstName: string;
  lastName: string;
}
| {
  typename: "socialMedia";
  userName: string;
  email: string;
}
>;

Now i want to write a new type that refers to Users > typename socialMedia

{
  typename: "socialMedia";
  userName: string;
  email: string;
}

I want the new type to be the code above

type userSocialMediaInfo = ?????

is this possible?

CodePudding user response:

It would be better to construct the Users type from two different types, this way you have access to the types without deriving, for example:

type Personal = {
  typename: "personal";
  firstName: string;
  lastName: string;
};

type SocialMedia = {
  typename: "socialMedia";
  userName: string;
  email: string;
};

type Users = Array<Personal| SocialMedia>;

Otherwise if you can't control the Users type, you can access its underlying variants by indexing it with number, and then intersecting the type with the relevant discriminator (playground):

type Users = Array<
| {
  typename: "personal";
  firstName: string;
  lastName: string;
}
| {
  typename: "socialMedia";
  userName: string;
  email: string;
}
>;

type userSocialMediaInfo = Users[number] & {  typename: "socialMedia";};

CodePudding user response:

This is possible with the Extract built-in type. First, you want to "unwrap" the array into the union. That's possible by indexing into it with number:

Users[number]

I'm using number in case the type could be at tuple. After we get the union, we can then use Extract. Here is what Extract does:

Constructs a type by extracting from Type all union members that are assignable to Union.

That should mean if we use:

Extract<Users[number], { typename: "socialMedia" }>

we'll get only the members of the union that have a type name of "socialMedia", since those are the only members that are assignable to { typename: "socialMedia" }.

Playground

CodePudding user response:

Short answer

type UserSocialMediaInfo = Extract<Users[0], { typename: "socialMedia" }>

Explanation

Users[0] - Take the first type from array.

Extract<...> - Extract type from union which is assignable to { typename: "socialMedia" }.

Better alternative

It would be more correct to adjust type generation logic to generate types separately.

type PersonelInfo = {
    typename: "personal";
    firstName: string;
    lastName: string;
}

type SocialMediaInfo = {
    typename: "socialMedia";
    userName: string;
    email: string;
}

type Users = Array<PersonelInfo | SocialMediaInfo>;
  • Related