TypeScriptFrontend

Advanced TypeScript Type Gymnastics

2024-02-2010 min
分享

Beyond Basic Types

Most TypeScript users stop at interfaces and generics. But the type system is a full programming language — conditional types, mapped types, and template literals let you encode complex invariants at compile time.

Conditional Types

Think of them as ternary operators for types:

type IsString<T> = T extends string ? true : false;

type A = IsString<"hello">; // true
type B = IsString<42>;      // false

Mapped Types

Transform every property in a type:

type Readonly<T> = {
  readonly [K in keyof T]: T[K];
};

type Optional<T> = {
  [K in keyof T]?: T[K];
};

Template Literal Types

String manipulation at the type level:

type EventName<T extends string> = `on${Capitalize<T>}`;

type ClickEvent = EventName<"click">; // "onClick"
type FocusEvent = EventName<"focus">; // "onFocus"

A Practical Example

Here's a type-safe event emitter:

type EventMap = {
  click: { x: number; y: number };
  focus: { target: string };
};

type Handler<T> = (payload: T) => void;

class Emitter<E extends Record<string, unknown>> {
  on<K extends keyof E>(event: K, handler: Handler<E[K]>): void {
    // implementation
  }
}

const emitter = new Emitter<EventMap>();
emitter.on("click", ({ x, y }) => {}); // fully typed

When to Stop

Type gymnastics are powerful but have a cost: readability. If a colleague can't understand your type in 30 seconds, simplify it. Types serve developers, not the other way around.

评论 (0)

还没有评论,来说点什么吧。