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>> // <- booleanTypeScripttype UnpackPromise<P> = ✨magic✨
UnpackPromise<Promise<string>> // <- string
UnpackPromise<Promise<number>> // <- number
UnpackPromise<Promise<boolean>> // <- booleanIf 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
: neverTypeScriptconst UnpackPromise = (P) =>
P === Promise<var T>
? T
: neverAnd 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 | stringTypeScripttype 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.