TypeScript · Types that pay for themselves

What TypeScript practices do you follow in production?

Easybest-practicesstrictapi-designUpdated Oct 2026
Quiz this track

Short answer

Prefer inference for locals and explicit types at boundaries, keep types narrow, avoid any, enable strict mode and validate untrusted data at runtime. Model states with discriminated unions.

Good TypeScript is less about clever type gymnastics and more about making invalid states hard to represent. The compiler should enforce the important contracts, while the code stays readable for the next person. Types are documentation that cannot drift silently.

  • Enable strict mode and fix errors with narrowing, not assertions
  • Annotate public APIs, exported functions and shared data shapes
  • Let local variables and simple callbacks be inferred
  • Use unknown plus validation for external data instead of any
  • Model finite states with discriminated unions and check them exhaustively
  • Keep generics only where they preserve a real relationship
  • Avoid deep conditional types unless they remove meaningful duplication
ts
type Result<T> =
  | { ok: true; value: T }
  | { ok: false; error: string };

function parseUser(input: unknown): Result<{ id: number }> {
  if (
    typeof input === "object" &&
    input !== null &&
    "id" in input &&
    typeof input.id === "number"
  ) {
    return { ok: true, value: { id: input.id } };
  }

  return { ok: false, error: "Invalid user" };
}

This example combines several practices: unknown at the boundary, a runtime check, a discriminated result and a precise success type. Callers must handle both branches, and the success branch carries the validated value. The type is doing real work rather than decorating the code.

Do not optimise for type-level cleverness. If a type takes more than a minute to explain to a teammate, a simpler model is usually better.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1Why prefer unknown over any at boundaries?
  2. 2When do you annotate a return type?
  3. 3How do you keep types readable for a team?
  4. 4When is a complex conditional type justified?

Say it in the interview

My defaults are strict mode, inference for locals, explicit types at public boundaries, and unknown plus validation for external data. I model finite states with discriminated unions and use never for exhaustiveness. I avoid any and heavy type gymnastics unless they remove real duplication. The goal is types that make invalid states hard to represent and errors easy to understand.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live TypeScript mock interview and get scored feedback on depth, clarity and confidence.