Lesson 2 · Module 0.2 — Reading TS syntax

Annotation vs inference vs definition: the three “type” words

It is easy to use type annotation, type inference, and type definition as if they were one thing. They are not three synonyms — they are three sources of a type. Tell them apart and you can answer the question that keeps recurring: “did I write this type, or did the compiler?”

The one distinction

A type can come from three places: you wrote it after a : (annotation), the compiler derived it from a value (inference), or it has a name you declared with type/interface (definition). When you read code, ask which source — the answer tells you whether a type is guaranteed or merely guessed.

The three sources, side by side

These terms are often used interchangeably. For writing code that is harmless. For reading code it hides the most useful question of all — where did this type actually come from? Here is the precise split:

sourcewho supplies the typehow you spot it
annotationyou, explicitlya : then a type you typed
inferencethe compiler, from a valueno : — type came from the =
definitiona name you declared oncea type / interface / .d.ts

All three on one small example

Watch the same word — User — play the role of a definition, then get used as an annotation, while a sibling line gets its type by inference:

// DEFINITION — a named type, declared once, reusable everywhere
interface User { id: number; name: string; }

// ANNOTATION — you wrote ": User" after the name; the type is User because you said so
const u: User = { id: 1, name: "Ada" };

// INFERENCE — no colon; the compiler reads the value 5 and decides the type is number
let n = 5;          // n : number   (you never typed "number")

Three lines, three sources. User is a definition — a name you can reuse. On u that name becomes an annotation — the explicit : User you wrote. And n has no annotation at all: its number type is inferred from the literal 5 on the right of the =.

Why the distinction earns its keep

An annotation is a promise you made — the compiler will hold you to it. An inferred type is the compiler's best guess from the value — change the value and the type silently changes with it. A definition is just a reusable label; on its own it annotates nothing until you attach it with a : (or a generic argument).

let mode = "dark";            // inferred as string — widened, not "dark"
const theme = "dark";          // inferred as "dark" — a literal type, because const can't change
let label: "dark" = "dark";   // annotated — YOU pinned the literal type yourself

Same three letters, three different types — because the source differs. Inference on a let widens to string; inference on a const keeps the literal; an annotation lets you force the literal even on a let. Reading the source tells you the type without running the compiler.

Don't conflate them

“Type information” is simply what the compiler knows about a type — it is the umbrella term, not a fourth source. const a: number = 5 and const b = 5 carry the same type information (number); only the source differs — you wrote one, the compiler inferred the other. (That hover tooltip showing const b: number is the compiler reading its type information back to you.) So every annotation is type information, but not all type information was annotated. When you read “TypeScript knows the type,” ask: knows it because you wrote it, or because it inferred it? Only the first is a guarantee you authored.

Check yourself

Recall, don’t re-read. (Answers reveal on click.)

In let n = 5;, the type number on n arrives by…
An interface User { … } on its own, before any :, is a…
Why is theme typed "dark" but mode typed string?

Primary source

The official handbook page that grounds this distinction — written annotations versus what the compiler works out for itself — is TypeScript Handbook — Everyday Types (see its “Type Annotations on Variables” and the note that you can often omit them). Best way to feel it: in the TS Playground, delete an annotation and hover the variable — the tooltip shows the inferred type the compiler chose in its place.

Try it yourself

Unsure whether a line is annotated or inferred? Decide its source first — ask “which source?” Next lesson (0.3) builds straight on this: as vs satisfies vs annotation — three ways to apply a type, with very different effects.