0

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?

2
  • Your question is a bit unclear. You want a type that corresponds to an element with typename: "socialMedial" What is wrong with the type you have given as an example? Does it not work for some reason? Commented Oct 8, 2022 at 12:16
  • @MattMorgan I want the new type to refer to the original type and I don't want to manually write the new type because the original type may change in the future and I don't want to change it again every time the original type changes. Commented Oct 8, 2022 at 12:25

3 Answers 3

3

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";};
Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

0

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>;

3 Comments

Users[number] would be better in case the type is a tuple.
In this particular case it is a multi type array and there is no any difference between T[0] and T[number].
In case the type changes and it's a tuple. I'm just being safe. There is no difference anyways, so might as well use the one that doesn't need changing if the type changes, right :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.