Course page
Log in

You are watching a free preview. Enroll to open all 25 lessons, track progress and ask the course tutor.

Enroll for $49.99

Section 1: Thinking in types

Inference and annotations

Article 11 min Lesson 2 of 25 Preview

You do not need to annotate everything. TypeScript infers types from values, and good TypeScript code relies on inference most of the time.

let count = 0;            // number
const name = "Mina";      // "Mina", a literal type, because const cannot change
const tags = ["a", "b"];  // string[]
const user = { id: 1, admin: false }; // { id: number; admin: boolean }

Hover over a variable in your editor to see what TypeScript inferred. Make this a habit. Most confusion with TypeScript comes from not knowing what type a value actually has.

Where to annotate

Annotate at boundaries, where information enters or leaves a piece of code:

  • Function parameters: TypeScript cannot guess what callers will pass.
  • Return types of exported functions: they document the contract and stop accidental changes.
  • Values that start empty: const ids: string[] = [], otherwise the array type is not useful.
  • Data from outside: API responses and parsed JSON.

Inside a function, let inference work:

function summary(prices: number[]): string {
  const total = prices.reduce((a, b) => a + b, 0); // inferred as number
  return `Total: ${total}`;
}

any, unknown and never

  • any turns off checking for a value. It spreads: anything you get from an any is also any. Avoid it except during migration.
  • unknown means "we do not know yet". You can store anything in it, but you must check its type before using it. It is the safe choice for data from outside.
  • never is the type of something that cannot happen, such as the result of a function that always throws. It becomes useful for exhaustive checks later.
const data: unknown = JSON.parse(text);
if (typeof data === "object" && data !== null && "id" in data) {
  // now TypeScript knows data has an id property
}

Excess property checks

When you pass an object literal directly to something with a declared type, TypeScript complains about extra properties, which catches typos such as colour instead of color. This check applies only to fresh object literals, which surprises people at first, so we explore it in the exercises.

Exercise: in the playground, remove annotations from a sample file one by one and check which ones inference can replace.

← → switch lessons