10LOC

#discriminated-unions

TypeScriptadvanced

Narrowing with in and tagged interfaces for a plugin system

interface LoggerPlugin { kind: "logger"; log(message: string): void }
interface CachePlugin { kind: "cache"; get(key: string): unknown }

export type AppPlugin = LoggerPlugin | CachePlugin;

Narrow a plugin union by checking which method it has, instead of switching on a kind tag, so adding a capability-only plugin needs no tag.

TypeScriptintermediate

Discriminated unions with an exhaustive switch and a never check

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number }
  | { kind: "rectangle"; width: number; height: number };

Make adding a new union case a compile error, not a silent runtime bug, using a switch that assigns the leftover case to never.