Lesson 16 / 25
Algebraic Data Types
Sum and product types, discriminated unions in TypeScript.
AND types and OR types
A product type combines several values at once: a record or tuple such as { x: number; y: number } holds an x and a y. A sum type is exactly one of several alternatives: a shape is a circle or a rectangle. Together they are algebraic data types (ADTs). Haskell, Rust, OCaml and Kotlin (sealed classes) have them built in. TypeScript models sum types as discriminated unions: each variant has a literal tag field such as kind, and the compiler narrows the type when you check it. ADTs let you make illegal states unrepresentable, for example a request that cannot be both loading and failed.
Making illegal states unrepresentable
Algebraic data types, pattern matching and Option/Result types model data precisely and force every case to be handled.
Replacing flags with a union
Booleans allow impossible combinations; a union does not.
// Before: 2 x 2 x optional fields allows nonsense states
type RequestStateLoose = {
loading: boolean;
error?: string;
data?: string[];
};
// After: a sum type of product types
type RequestState =
| { kind: 'idle' }
| { kind: 'loading' }
| { kind: 'failed'; error: string }
| { kind: 'loaded'; data: string[] };
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'rect'; width: number; height: number };The same type in Haskell
data Shape = Circle Double | Rect Double Double declares a sum type with two constructors; each constructor holds a product of fields.
Quick check: What is a sum type?
- A number type used for addition
- A record that holds several fields at once
- A value that is exactly one of several tagged alternatives
- A list of all possible values
Answer
A value that is exactly one of several tagged alternatives — Sum = OR, product = AND.