TypeScript

Types and inference

What you annotate, what the compiler works out for itself, and why any is a hole.

After this lesson you can

  • Annotate a variable, a parameter and a return type
  • Say when to annotate and when to let inference do it
  • Explain the difference between any and unknown

TypeScript is JavaScript with types checked before the code runs. Nothing survives to runtime: the types are erased, and what ships is JavaScript.

const name: string = "Nino";
const years: number = 5;
const remote: boolean = true;

Those annotations are all unnecessary. TypeScript already knows "Nino" is a string. Writing the type again adds nothing and gives you a second thing to keep in sync.

Annotate the edges

The useful rule: annotate what crosses a boundary, infer the rest.

function fullName(first: string, last: string): string {
  const joined = `${first} ${last}`;  // inferred as string
  return joined;
}

Parameters must be annotated, because nothing tells the compiler what a caller will pass. A return type is optional but worth writing on anything exported: it makes the function's promise explicit, and it means a mistake inside the function is reported inside the function rather than at every call site.

Try it

What the compiler works out on its owntypescript-5
export function describe(): string {  // No annotations anywhere; TypeScript infers every one of these.  const name = "Nino";  const years = 5;  const skills = ["C#", "PostgreSQL"];   // skills is string[], so .join is available and .toFixed is not.  return `${name}, ${years} years, ${skills.join(" and ")}`;}
What to look for

any and unknown

any switches the checker off for that value. Everything is allowed, and the hole spreads: anything derived from an any is also unchecked.

unknown is the safe version. You can hold it, pass it, store it — you just cannot use it until you have proved what it is.

function parse(raw: unknown): number {
  if (typeof raw === "number") return raw;   // proved
  if (typeof raw === "string") return Number(raw);
  throw new Error("not a number");
}

Whenever you are about to write any, unknown plus a check is almost always what you actually wanted.

Try it yourself

2 visible tests · 2 hidden tests

Implement average(nums: number[]): number that returns the mean of the array. An empty array has no mean — return 0 rather than NaN or throwing.

  • average([2,4,6])
  • average([10])
Loading editor…

Sign up to check the hidden tests and save your progress. Sign up