Compile-time TypeScript tricks with no runtime code and no branded types. Every trick is checked by the compiler.
Each trick lives in tricks/<name>/. index.ts has the trick, cases that should pass, and cases that should fail. README.md explains how it works and where it stops working. The failing cases are marked with // @ts-expect-error, and TypeScript reports an error if one of those lines doesn't actually fail. So if the check passes, every case behaves as shown.
Strings with an exact length, e.g. a 3-character country code or a 4-digit PIN. · Playground
type Pin = `${D}${D}${D}${D}${End}`; // exactly 4 digits
const pin: Pin = "0427";
// @ts-expect-error not a digit
const letter: Pin = "04a7";Strings between a minimum and maximum length. · Playground
type Username = `${C}${C}${C}${O}${O}${O}${O}${O}${End}`; // 3 to 8 characters
const b: Username = "danfry";
// @ts-expect-error too long
const d: Username = "danfrydev1";3-letter uppercase codes like GBP, using Uppercase<string> as a type. · Playground
type CurrencyCode = Uppercase<string> & `${C}${C}${C}${End}`; // 3 uppercase characters
const gbp: CurrencyCode = "GBP";
// @ts-expect-error lowercase
const lower: CurrencyCode = "gbp";Number literals from 1 to 65535. · Playground
listen(65535);
// @ts-expect-error
listen(65536);IPv4 addresses with each part from 0 to 255. · Playground
ip("192.168.0.1");
// @ts-expect-error 256 is out of range
ip("256.0.0.1");MAJOR.MINOR.PATCH[-prerelease] with no leading zeros. · Playground
const b: SemVer = "10.0.0-beta.1";
// @ts-expect-error leading zero
const c: SemVer = "1.02.3";YYYY-MM-DD with the right number of days in each month, including leap years. · Playground
const ok: IsoDate[] = ["2026-10-20", "2028-02-29", "2000-02-29"];
// @ts-expect-error
const b: IsoDate = "1900-02-29";Digit strings that pass the Luhn checksum (credit card numbers). · Playground
card("4242424242424242");
// @ts-expect-error one digit off
card("4242424242424241");13-digit barcodes (EAN-13 and ISBN-13) with a valid check digit. · Playground
barcode("9780306406157"); // ISBN-13
// @ts-expect-error wrong check digit
barcode("4006381333932");CSS hex colours like #fff or #1a2b3c80. · Playground
color("#1a2B3c");
// @ts-expect-error g isn't hex
color("#ggg");UUIDs in the 8-4-4-4-12 hex format. · Playground
uuid("123e4567-e89b-12d3-a456-426614174000");
// @ts-expect-error z isn't hex
uuid("123e4567-e89b-12d3-a456-42661417400z");A format function whose arguments are typed from its format string. · Playground
format("%s is %d years old", "Dan", 31);
// @ts-expect-error %d needs a number
format("%s is %d years old", "Dan", "31");Props that need one of two options but not both, like href or onClick. · Playground
type ButtonProps = { label: string } & Xor<{ href: string }, { onClick: () => void }>;
// @ts-expect-error both href and onClick
const both: ButtonProps = { label: "Huh", href: "/docs", onClick: () => {} };Every file compiles under tsc --strict --noEmit. CI runs the check on TypeScript 7.0.2 and 5.9.3.
pnpm install
pnpm checkThe repo scripts are TypeScript too, and run directly on Node 24 or later with no build step. pnpm check type-checks them first.
Each trick is checked in its own tsc run, because the tricks are standalone scripts that reuse type names like End, D and N.
pnpm check also checks that the docs match the code. Every playground link has to decode back to its index.ts, every trick README has to embed its index.ts, and every line of the snippets above has to appear in the trick's index.ts. After editing a trick, run pnpm docs:sync to regenerate the links and embedded code.
New tricks are welcome. Each one needs to:
- work at the type level only, with no runtime logic and no branded types. Test cases can be
constassignments and calls todeclared functions; - live in its own
tricks/<name>/folder, as anindex.tsand aREADME.md; - show cases that should pass, and cases that should fail marked with
// @ts-expect-error; - pass
pnpm checkon both TypeScript 7.0.2 and 5.9.3.
The trick's README.md needs a one-line description, an empty ts code block, [Open in TS Playground][playground], a short "How it works", and "Limits". Use an existing trick as a template. Add a ### [<name>](tricks/<name>) section to this README with a few lines copied from index.ts, then run pnpm docs:sync to fill in the code and playground links.