Lesson 1 · Module 0.1 — Reading TS syntax

Reading a type annotation: the : and the =>

One confusion comes up again and again when you start reading TypeScript: after a :, is that a return type or a variable type? And does => mean “arrow function” or something else? Both questions have the same answer — position decides meaning. Learn the two positions and TS syntax stops being ambiguous.

The one rule

Every piece of TypeScript is in one of two worlds: type position (annotations — erased at runtime) or value position (real JavaScript — survives at runtime). The same symbols (:, =>) mean different things in each. Find the world first; the meaning follows.

The boundary marker: : starts a type, = starts a value

Here is the core maxim, made precise:

Everything after a : and before the next = is type information. Everything after = is a real runtime value.
const add: (a: number, b: number) => number = (a, b) => a + b;
//         └──────────── TYPE ────────────┘   └─── VALUE ───┘

The left => lives in the type; the right => lives in the value. They are not the same thing — see below.

The : means three things — told apart by where it sits

where the : sitswhat follows itexample
after a parameter namethat parameter’s typef(x: string)
after the parameter list )the return typef(x: string): number
after a variable / property namethat variable’s typeconst u: User

So in a function declaration, the : before the body is a return type:

function greet(name: string): string { return `hi ${name}`; }
//                  ^param type   ^return type

But when you annotate a variable that happens to hold a function, the whole function type is the variable’s type — and the return type is buried inside it:

const greet: (name: string) => string = (name) => `hi ${name}`;
//           └ the variable's type ─┘   └──── the value ─────┘
//           the return type is the `string` after the => inside the type

Same return type, two different places, because one is a declaration and the other is an annotation. That is the whole confusion, resolved.

The => means two things — told apart by world

world=> meansleft / rightsurvives runtime?
type positiona function typeparams / return typeno — erased
value positionan arrow functionparams / function bodyyes — real code

The classic proof — look at what each compiles to:

let MakePoint: () => { x: number; y: number };   // TYPE position
// compiles to:  let MakePoint;        (the whole annotation is erased)

const MakePoint = () => ({ x: 1, y: 2 });        // VALUE position
// compiles to:  const MakePoint = () => ({ x: 1, y: 2 });   (real function survives)

Top one is a description of a function (a function type); bottom one is a function. The => looks identical but lives in different worlds.

How to find the world (a 3-second check)

  1. Is the code after a :, or inside a type / interface / generic <…>? → type world. A => here is a function type; its right side is a return type.
  2. Is the code after a =, or being returned / passed as an argument? → value world. A => here is an arrow function; its right side is the body.

Try it on a real-world example

Here is a curried thunk (the dispatch/getState puzzle, common in Redux) that often trips people up. Watch the boundary — same shape on each side of the =, opposite worlds:

const addToCart:
    (id: string, qty: number) => (dispatch: Dispatch, getState: () => State) => Promise<void>
//  └─ TYPE (after : , before = ): every => is a function type; final return is Promise<void>
  = (id, qty) => async (dispatch, getState) => { ... };
//  └─ VALUE (after = ): two real arrow functions, one returning the other

On the type side, (dispatch, getState) are parameter types and each => is a function type. On the value side, they’re real parameters and each => is a real arrow function. The left describes the function; the right is it.

Check yourself

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

In const f: (a: number) => string = (a) => "x";, the left => is…
In function area(r: number): number, the second : number is the…
Why does let p: () => number; compile to just let p;?

Primary source

The official handbook page that nails the function-type-vs-arrow distinction is TypeScript Handbook — Function Type Expressions. For the “types are erased” idea, see Everyday Types. Best way to feel it: paste both MakePoint versions into the TS Playground and watch the .js output panel.

Try it yourself

Got a tricky line? Decide its world first — ask “type world or value world?” Next lesson (0.2) builds straight on this: annotation vs. inference vs. definition — three “type” words that are easy to mix up.