I have a type like below:
type Entity =
| {
type: 'user' | 'person';
id: string;
}
| {
type: 'animal';
id: number;
};
Now I want to extract the types from it:
type Animal = Extract<Entity, {type: 'animal'}> – works perfectly (returns { type: 'animal'; id: number; });
type User = Extract<Entity, {type: 'user'}> – returns never.
How can I make it return { type: 'user'; id: string; }
?
>Solution :
The provided documenation for Extract<T, U> says:
Extract from T those types that are assignable to U
And { type: 'user' | 'person', id: string } is not assignable to { type: 'user' }
declare const entity: Entity
const user: { type: 'user' } = entity
/*
Type 'Entity' is not assignable to type '{ type: "user"; }'.
Type '{ type: "user" | "person"; id: string; }' is not assignable to type '{ type: "user"; }'.
Types of property 'type' are incompatible.
Type '"user" | "person"' is not assignable to type '"user"'.
Type '"person"' is not assignable to type '"user"'.(2322)
*/
Which means you cannot use Extract to do this.
But what you can do is use an intersection (&), which will trim away any union members that cannot be matched by that discriminant.
type User = Entity & { type: 'user' }
const user: User = { type: 'user', id: 'abc' }
user.id // type: string