Reputation: 3
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?
Upvotes: 0
Views: 1834
Reputation: 26324
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 toUnion
.
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" }
.
Upvotes: 0
Reputation: 116
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>;
Upvotes: 0
Reputation: 707
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";};
Upvotes: 3