Lab 01: Type System Limits

Time: 60 minutes | Level: Architect | Docker: node:20-alpine

Overview

Push the TypeScript type system to its limits: type instantiation depth, recursive type performance, type-level Fibonacci and FizzBuzz, tsc --diagnostics profiling, @ts-expect-error vs assertion functions, and satisfies for inference without widening.


Step 1: Understanding Type Instantiation Depth

// TypeScript has a default depth limit of ~100 recursive instantiations
// Compiler option: --maxNodeModuleJsDepth (different concern)

// SLOW: deeply recursive type
type Repeat<T, N extends number, A extends T[] = []> =
  A['length'] extends N ? A : Repeat<T, N, [...A, T]>;

// type R50 = Repeat<string, 50>;  // OK
// type R100 = Repeat<string, 100>; // Type instantiation is excessively deep

// FAST: alternative using tail recursion simulation
type BuildTuple<L extends number, T extends any[] = []> =
  T['length'] extends L ? T : BuildTuple<L, [...T, unknown]>;

type TupleOf<T, N extends number> =
  BuildTuple<N> extends infer U
    ? { [K in keyof U]: T }
    : never;

type Five = TupleOf<string, 5>; // [string, string, string, string, string]

Step 2: Type-Level Computation — FizzBuzz


Step 3: Avoiding Slow Type Patterns


Step 4: satisfies Operator (TypeScript 4.9+)


Step 5: @ts-expect-error vs Assertion Functions


Step 6: const Type Parameters (TypeScript 5.0)


Step 7: NoInfer (TypeScript 5.4)


Step 8: Capstone — Type-Level FizzBuzz + Runtime Verification

📸 Verified Output:


Summary

Feature
Version
Use Case

Recursive types

All

Data structures, parsing

satisfies

4.9

Validate + keep narrow type

const type param

5.0

Infer literals not widened

NoInfer<T>

5.4

Control inference site

@ts-expect-error

All

Type-level tests

Assertion functions

All

Runtime + type narrowing

tsc --diagnostics

All

Performance profiling

Depth limit

All

~100 recursions default

Last updated