TypeScript infer Keyword
TypeScript infer Keyword with examples
In this article, I'll show you how we can use the infer
keyword to extract types from generics. Let's use Promise
as an example.
type UnpackPromise<P> = ✨magic✨
UnpackPromise<Promise<string>> // <- string
UnpackPromise<Promise<number>> // <- number
UnpackPromise<Promise<boolean>> // <- boolean
TypeScripttype UnpackPromise<P> = ✨magic✨
UnpackPromise<Promise<string>> // <- string
UnpackPromise<Promise<number>> // <- number
UnpackPromise<Promise<boolean>> // <- boolean
If P
is a subset of a Promise
of T
, we want to return T
. Otherwise, we return never
, which represents something that should never happen.
type UnpackPromise<P> = P extends Promise<T> ? T : never;
TypeScripttype UnpackPromise<P> = P extends Promise<T> ? T : never;
But that doesn't work, because T
doesn't exist yet.
Let's compare that to a function, and you'll see what I mean.
const UnpackPromise = (P) =>
P === Promise<T>
? T
: never
TypeScriptconst UnpackPromise = (P) =>
P === Promise<T>
? T
: never
P
is an argument, but where is T
coming from?
In a regular function, you would solve this by creating a variable called T
. Something like this:
const UnpackPromise = (P) =>
P === Promise<var T>
? T
: never
TypeScriptconst UnpackPromise = (P) =>
P === Promise<var T>
? T
: never
And that's where the infer
keyword comes into play. It works kinda like a type variable declaration.
type UnpackPromise<P> = P extends Promise<infer T> ? T : never;
TypeScripttype UnpackPromise<P> = P extends Promise<infer T> ? T : never;
If P
is a subset of Promise
, we tell TypeScript to infer the inner type of that Promise
and save it in a type called T
. Then, we return T
.
type UnpackPromise<P> =
P extends Promise<infer T>
? T
: never
UnpackPromise<Promise<string>> // <- string
UnpackPromise<Promise<number>> // <- number
UnpackPromise<Promise<boolean>> // <- boolean
UnpackPromise<Promise<Array<Date>>> // <- Array<Date>
UnpackPromise<Promise<boolean | string>> // <- boolean | string
TypeScripttype UnpackPromise<P> =
P extends Promise<infer T>
? T
: never
UnpackPromise<Promise<string>> // <- string
UnpackPromise<Promise<number>> // <- number
UnpackPromise<Promise<boolean>> // <- boolean
UnpackPromise<Promise<Array<Date>>> // <- Array<Date>
UnpackPromise<Promise<boolean | string>> // <- boolean | string
Conclusion
References are below.
There's a lot more to the infer
keyword, but that's what I could fit in a one-minute video. If you want to dive deeper into TypeScript, I have a series about TypeScript narrowing. You can read the full series, for free, on my blog.
Leave a like, have a great day and see you soon.