Programming language

TypeScript

TypeScript is a statically checked superset of JavaScript that adds syntax for describing values, APIs, and program states before execution.

What is TypeScript and what does it do?

TypeScript extends JavaScript with syntax for types and a static checker. It can describe object shapes, function contracts, generic relationships, and the possible states of a value. The toolchain reports inconsistencies before the generated JavaScript runs.

Its type system provides design feedback. A useful type explains a real boundary or state transition. It should make the runtime behavior easier to understand, not become a separate puzzle above it.

Types disappear before execution

TypeScript checks source code, then emits JavaScript without its type annotations. The path can be pictured like this:

  1. Write TypeScript source and type declarations.
  2. Let the checker compare assignments, calls, and control flow.
  3. Emit JavaScript for the selected runtime target.
  4. Validate real external values while the program runs.

The last step is essential. An interface cannot inspect a network response, storage entry, or configuration file after the types have been erased.

Unknown data must earn a type

Untrusted input should start as unknown. A type guard can inspect it and narrow the value for later code.

type User = { id: number; name: string };

function isUser(value: unknown): value is User {
  if (typeof value !== "object" || value === null) return false;
  const item = value as Record<string, unknown>;
  return typeof item.id === "number"
    && typeof item.name === "string";
}

The assertion only gives the temporary record a shape that can be inspected. The returned boolean and type predicate are based on runtime checks.

Model states, not just properties

A union can make invalid combinations harder to express.

State Data that belongs to it
idle No result and no error
loading Request identity or progress
success Valid result
failure Error information

One discriminant with state-specific data is clearer than several optional properties whose combinations need to be guessed. Exhaustive checks then reveal a missing branch when the union grows.

Strictness is a design choice

Compiler options determine how much uncertainty the checker accepts. Strict settings are a strong default for new code because they expose nullability, implicit any, and unchecked assumptions early.

There is still a boundary. Complex conditional or generic types can cost more attention than they save, and an assertion can silence the checker without proving anything. A type should be simplified when its explanation becomes longer than the behavior it protects.