GGistDev

Values and Types in TypeScript

Understand the core type system and common value categories.

Primitives

  • string, number, boolean
  • bigint: integers beyond 2^53-1: 123n
  • symbol: unique identifiers
  • null and undefined: enable strictNullChecks to model absence precisely
let s: string = "hi";
let n: number = 42;
let ok: boolean = true;
let big: bigint = 9007199254740993n;
let sym: symbol = Symbol("id");

any vs unknown vs never vs void

  • any: opt-out of type safety; avoid except at boundaries
  • unknown: like any but forces narrowing before use
  • never: a function that never returns (throws or infinite loop)
  • void: absence of a return value
function fail(msg: string): never { throw new Error(msg); }
function log(x: unknown): void {
  if (typeof x === "string") console.log(x.toUpperCase());
}

Objects, arrays, tuples

const user: { id: number; name: string } = { id: 1, name: "Ada" };
const nums: number[] = [1, 2, 3];
const pair: [string, number] = ["age", 42];

Use readonly arrays and tuples when order/length is fixed.

Literal types and widening

let dir: "up" | "down";
dir = "up"; // ok
// dir = "left"; // error

Avoid unwanted widening by using as const or satisfies.

const cfg = { mode: "prod", retries: 3 } as const; // literal inference

Template literal types

type EventName = `on${"Click" | "Hover"}`; // "onClick" | "onHover"

Structural typing

Compatibility is based on shape, not nominal identity.

interface Named { name: string }
function printName(x: Named) { console.log(x.name); }
printName({ name: "Lin" }); // ok (extra props allowed at call sites)

Narrowing basics

Control-flow analysis refines types.

function len(x: string | string[]) {
  return typeof x === "string" ? x.length : x.length;
}

Summary

  • Prefer unknown over any; use literal types for exact values
  • Arrays/tuples model lists and fixed positions; structural typing favors flexibility