thecodex.expert · The Codex Family of Knowledge
TypeScript

Type Inference

Well-written TypeScript actually has relatively FEW explicit type annotations — the compiler infers most types automatically, and over-annotating is itself considered a code smell.

TypeScript 6.0 Annotations are the exception Last verified:
Canonical Definition

TypeScript infers a variable's type from its initializer, a function's return type from its return statements, and can even infer a parameter's type from the expected type of the position it's used in ("contextual typing"). This means idiomatic TypeScript code annotates far less than newcomers expect — explicit types are reserved for function parameters (which cannot be inferred from nothing) and cases where inference genuinely can't determine the intended type.

Inference from initializers

None of these need an explicit type annotation at all — TypeScript reads the initializer and infers the precise type automatically.

TypeScriptinitializer_inference.ts
let name = "Alice";        // inferred: string
let age = 30;               // inferred: number
let scores = [90, 85, 78]; // inferred: number[]

// name = 42;   // COMPILE ERROR: even without an explicit annotation, the inferred type still applies

Return type inference

The return type is inferred from every return statement in the function, unioned together if they differ — an explicit annotation is still good practice for public API functions, since it documents intent and catches an accidental wrong return immediately, even though it's not required.

TypeScriptreturn_inference.ts
function double(x: number) {   // return type inferred, not annotated
    return x * 2;                // TypeScript infers: number
}

function maybeDouble(x: number, shouldDouble: boolean) {
    if (shouldDouble) return x * 2;
    return undefined;
}   // inferred return type: number | undefined

Contextual typing: inferring parameter types from usage

Because Array.prototype.map's signature expects a callback of a known shape, TypeScript can infer n's type as number from context, with zero annotation needed inside the callback itself.

TypeScriptcontextual_typing.ts
const numbers = [1, 2, 3];

numbers.map((n) => n * 2);
// n's type is inferred as `number` from the array's element type —
// no annotation needed on n at all

Sources

1
Microsoft. TypeScript Handbook, "Type Inference", typescriptlang.org/docs/handbook/type-inference.html.