typestar

Recursive types in TypeScript

A type that refers to itself, which is how JSON and trees are typed.

type Json =
  | string
  | number
  | boolean
  | null
  | Json[]
  | { [key: string]: Json };

interface TreeNode<T> {
  value: T;
  children: TreeNode<T>[];
}

type Paths<T> = T extends object
  ? { [K in keyof T & string]: K | `${K}.${Paths<T[K]>}` }[keyof T & string]
  : never;

type Config = { server: { port: number; host: string }; debug: boolean };
type ConfigPath = Paths<Config>;

const document: Json = { runs: [{ lang: "ts", tpm: 98 }], ok: true };
const tree: TreeNode<string> = {
  value: "root",
  children: [{ value: "leaf", children: [] }],
};
const path: ConfigPath = "server.port";
console.log(typeof document, tree.children.length, path);

How it works

  1. The recursion must go through an object, array or union.
  2. A depth limit keeps the compiler from giving up.
  3. This is the honest type for anything JSON-shaped.

Keywords and builtins used here

The run, in numbers

Lines
27
Characters to type
635
Tokens
200
Three-star pace
110 tpm

At the three-star pace of 110 tokens a minute, this run takes about 109 seconds.

Type this snippet

Step 2 of 2 in Strings & recursion, step 8 of 12 in Type-level programming.

← Previous Next →