NoInfer<T>
Prevents TypeScript from inferring a type parameter from the usage site where NoInfer is applied, giving priority to other inference sites.
Definition
type NoInfer<T> = intrinsic;Examples
function createFSM<S extends string>(
initial: S,
transitions: Record<S, S[]>,
) {}
// Without NoInfer, S is inferred from both arguments
// With NoInfer on transitions, S is inferred only from initial
function createFSMFixed<S extends string>(
initial: S,
transitions: Record<NoInfer<S>, NoInfer<S>[]>,
) {}
// Error: "unknown" is not assignable
createFSMFixed("idle", {
idle: ["running"],
running: ["idle", "unknown"], // catches typos!
});function getOrDefault<T>(values: T[], defaultValue: NoInfer<T>): T {
return values.length > 0 ? values[0] : defaultValue;
}
// T is inferred from 'values' only
getOrDefault([1, 2, 3], 0); // OK
// getOrDefault([1, 2, 3], "oops"); // Error: string not assignable to numberfunction emit<T extends string>(
event: T,
payload: NoInfer<T> extends "error" ? Error : unknown,
): void {
console.log(event, payload);
}
emit("error", new Error("fail")); // OK
emit("click", { x: 10 }); // OKCommon Use Cases
- 1Preventing inference from default values or fallback parameters
- 2Ensuring type parameters are inferred from primary sources
- 3State machine definitions where states come from one site
- 4Function overloads simplified with controlled inference
- 5Library APIs where user intent should drive inference
Understanding NoInfer<T>
NoInfer<T> is a utility type introduced in TypeScript 5.4 that blocks type inference at a specific usage site. When TypeScript infers a type parameter, it gathers candidates from all positions where that parameter appears. NoInfer tells the compiler to skip a particular position, so the type parameter is inferred from the remaining positions only.
This solves a common problem in generic function design. Consider a function with parameters (values: T[], defaultValue: T)—TypeScript infers T from both parameters. If you pass [1, 2, 3] as values and "fallback" as default, T becomes number | string instead of just number. By changing to (values: T[], defaultValue: NoInfer<T>), T is inferred only from values, and the default must match.
NoInfer is especially valuable for state machine libraries. When defining transitions like Record<State, State[]>, you want State to be inferred from the initial state parameter, not from the transition map. Without NoInfer, typos in the transition map silently widen the State type. With NoInfer on the transitions, typos are caught as errors.
Before NoInfer existed, library authors used workarounds like intersecting with {} or using conditional types to block inference. These hacks were fragile and confusing. NoInfer provides a clean, intentional mechanism for the same purpose.
NoInfer is an intrinsic type, meaning its behavior is built into the compiler rather than expressible in user-land TypeScript. It has no runtime effect—it purely influences type inference during compilation. The resulting type is identical to T; only the inference behavior changes.
Related Types
infer keywordThe infer keyword declares a type variable within a conditional type's extends clause, extracting and capturing part of a type for use in the true branch.
satisfies operatorThe satisfies operator validates that a value matches a type without widening the value's inferred type, preserving literal types and specific structure.
Conditional TypesConditional types select one of two types based on a condition expressed as an extends clause, enabling type-level branching logic.
More Advanced Patterns
Explore TypeScript Types
Browse our complete reference of 30 TypeScript utility types with definitions, examples, and explanations.