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
Tmatches 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 oninferto 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.