CATHODE COASTaccess to tools
1 min read

型は宇宙だ — TypeScript型レベルプログラミング

条件型・mapped types・再帰で、型システムの上に小さな計算機を作る。Zod との接続まで。


TypeScript の型システムは、それ自体がチューリング完全に近い小さな言語だ。 値の世界とは別に、型の世界で計算することができる。

条件型とインフラ

条件型 (extends ? :)と infer を組み合わせると、型から型を取り出せる。

infer.ts
type ElementOf<T> = T extends readonly (infer U)[] ? U : never;
 
type A = ElementOf<string[]>; // string
type B = ElementOf<[1, 2, 3]>; // 1 | 2 | 3

再帰で計算する

タプルの長さを使えば、型レベルで自然数を表現できる。

length.ts
type Length<T extends readonly unknown[]> = T["length"];
type Push<T extends readonly unknown[], V> = [...T, V];
 
type One = Push<[], unknown>; // [unknown]
type Two = Push<One, unknown>; // [unknown, unknown]
type N = Length<Two>; // 2

Zod との接続

型レベルの厳密さは、境界(API レスポンスなど)では崩れる。 そこは Zod でランタイムに検証し、z.infer で静的型へ橋渡しする。

schema.ts
import { z } from "zod";
 
const Post = z.object({
  title: z.string(),
  tags: z.array(z.string()),
});
 
type Post = z.infer<typeof Post>; // { title: string; tags: string[] }

型は宇宙だ。だがその宇宙の縁では、ランタイムの検証が現実を守っている。