Extract
is a utitly type in Typescript
that allows you to create a new type by extracting a subset of an existing type.
This article is inspired from this article from Matt Pocock
.
Here are few possible ways to use
Extract
inTypescript
:
Table of contents
- Get a member of an union
- Get multiple members from an union
- Get a member of a discriminated union
- Get multiple members of a discriminated union
- Get members of a discriminated union by shape
- Get members by a type
- Get strings containing a substring from an union
- Get strings with one of several possible values from an union
- Conclusion
Get a member of an union
We can extract a member of union
by using Extract
. The first argument is the full union, and the second argument is the member of the union that we want to get.
type Animal = "cat" | "dog" | "bird" | "fish";
type OnlyCat = Extract<Animal, "cat">; // 'cat'
Get multiple members from an union
We can even get mulitple members from an union by using Extract
. Here is how:
type Animal = "cat" | "dog" | "bird" | "fish";
type ExtractType = Extract<Animal, "cat" | "dog">; // 'cat' | 'dog
Even if we pass a value to Extract
that doesn't exist in the union, Typescript will return the values that exists in the union.
type Animal = "cat" | "dog" | "bird" | "fish";
type ExtractType = Extract<Animal, "cat" | "dog" | "tiger">; // 'cat' | 'dog'
Get a member of a discriminated union
type Shape =
| {
type: 'square'
}
| {
type: 'circle'
}
| {
type: 'triangle'
}
A discriminated union type is one where each member has a discriminant property. The discriminant property is a common property that can be used to discriminate between the other members. In the example above, the type
property is used to discriminate between the different shapes.
We can extract a member of the discriminated union by using Extract
like this:
type SqaureShape = Extract<Shape, {type: 'square'}> // { type: 'square' }
Get multiple members of a discriminated union
We can also extract multiple members of a discriminated union:
type SqaureAndCircleShape = Extract<Shape, {type: 'square'} | {type: 'circle'}>
// { type: 'square' } | { type: 'circle' }
This works even if the union members have other properties attached to them.
type Shape =
| {
type: 'square';
size: number;
}
| {
type: 'circle'
}
| {
type: 'triangle'
}
type SqaureAndCircleShape = Extract<Shape, {type: 'square'} | {type: 'circle'}>
// {type: 'square'; size: number;} | { type: 'circle' }
You can also get multiple members of the discriminated union by passing a union
to the type
property:
type Shape =
| {
type: 'square';
size: number;
}
| {
type: 'circle'
}
| {
type: 'triangle'
}
type SqaureAndCircleShape = Extract<Shape, {type: 'square' | 'circle'}>
// {type: 'square'; size: number;} | { type: 'circle' }
Get members of a discriminated union by shape
type Routes =
| {
route: '/user'
search: {
id: string
}
}
| {
route: '/user/create'
}
| {
route: '/user/edit'
search: {
id: string
}
}
type RoutesWithSearch = Extract<
Routes,
{
search: any
}
>
/*
{
route: '/user';
search: {
id: string;
};
} | {
route: '/user/edit';
search: {
id: string;
};
}
*/
To get the members of union you don't need to always include the discriminator
(in this case, route
) in the second argument. You can just pass the shape
of the members you want to get.
In this case, we want to extract the types from the Routes union type that have a search property.
Get members by a type
type allTypes = 'admin' | 'user' | 5 | 6 | 7 | true
type onlyNumbers = Extract<allTypes, number> // 5 | 6 | 7
In the example above, we remove all literals that don't match the number type from the allTypes
union. Hence, we are only getting the numbers.
Get strings containing a substring from an union
type keys = 'userId' | 'tweetId' | 'userName' | 'tweetName'
type UserKey = Extract<keys, `${'user'}${string}`> // "userId" | "userName"
The resulting UserKey
type will be a union of the string literals from strings that start with the string "user." This case will include only the userId
and userName
string literals.
Get strings with one of several possible values from an union
type keys = 'userId' | 'tweetId' | 'id' | 'userName' | 'friendName'
type OnlyIdKey = Extract<keys, `${string}${'id' | 'Id'}${string}`>
// "userId" | "tweetId" | "id"
You can also use Extract
to get all strings from a union that contain one of several possible substrings.
In this case, the resulting OnlyIdKey
type will be a union
of the string literals from keys
containing the id
or Id
. This case will include the userId
, tweetId
, and id
string literals.
Conclusion
So that's it, guys. I hope you found the article helpful. Extract
is a utility type that can be used in many ways. If you think there are more ways to use Extract,
please let me know in the comments. Thanks for reading the article. I will see you all in my next article🐸.
Visit:
👨💻My Portfolio
🏞️My Fiverr
Top comments (8)
How does Extract differ from Pick?
Extract
creates a new type by selecting some of the original types, whilePick
is used to create a new type by choosing some of the original properties.I had same quesiton :)
I really liked the bit about 'Get strings containing a substring from an union'. Tbf I didn't know you could use string literals that way for TS types, especially not inside of generics.
Thanks, glad you learned a new thing today from the article😊
Great post!
I am not sure but does Extract<a, b> mean a & b ?
Looks like somebody likes to steal work of others?
Stop doing that, it's pathetic and unethical.
This article is a rewrite of this one posted a week ago:
totaltypescript.com/uses-for-exclu...
Some comments have been hidden by the post's author - find out more