TypeScript’s infer keyword: when generics aren't enough
If you’ve been using TypeScript for a while, you’re probably comfortable with generics. They let you write reusable types and functions. Pretty handy.
But sometimes generics hit a wall.
What if you want to extract the return type of a function? Or peel off the inner value of a Promise? Or get the second argument of a function type?
That’s where infer
comes in.
What is infer
? #
infer
is a keyword you can use inside a conditional type to extract a
piece of a type pattern.
The structure looks like this:
|
|
It reads like:
If
T
matches this pattern, grab the type inside asU
. Otherwise, useFallback
.
It’s TypeScript’s way of saying:
“Try to deduce this type for me from the structure of something else.”
Example 1: Get the return type of a function #
Let’s say you have a function type:
|
|
You want to extract number
from that.
Here’s how:
|
|
Example 2: Recursively unwrap a deeply nested Promise #
Imagine this type:
|
|
Want to get the string
?
|
|
Example 3: Get the second argument of a function #
Let’s say you’re building a middleware pipeline. You need to extract the res
object from a handler type:
|
|
You want just the res
.
|
|
Example 4: Rebuild ReturnType<T>
from scratch #
TypeScript’s built-in utility types (ReturnType
, Parameters
, etc.) use
infer
under the hood.
Here’s your own version of ReturnType
:
|
|
Same deal. You match a structure and pull out a piece.
Real-world use cases #
- React HOCs: Extracting props from a component type.
- API layers: Getting the shape of return data from an async call.
- Function pipelines: Inferring argument or return types of composed functions.
- Tooling: Libraries like
ts-toolbelt
,type-fest
, and even Redux heavily rely oninfer
to keep types ergonomic.
Final thoughts #
infer
is the kind of tool that separates day-to-day TypeScript use from
serious type system wizardry.
If you’ve ever thought:
“There must be a way to extract just this part of the type…”
…there probably is. And it probably involves infer
.