Semua ArtikelJavaScript / TypeScript
5 Februari 2025·10 menit baca

TypeScript Advanced Patterns yang Wajib Dikuasai

TypeScript bukan sekadar JavaScript dengan type annotation. Ada sejumlah pola lanjutan yang — ketika dikuasai — akan mengubah cara kamu menulis kode secara fundamental.

1. Conditional Types

Conditional types memungkinkan kamu membuat tipe yang bergantung pada kondisi tipe lain. Sintaksnya mirip ternary operator dan sangat powerful untuk utility types.

ts·Conditional Types
type IsString<T> = T extends string ? "ya, string" : "bukan string";

type A = IsString<string>;  // "ya, string"
type B = IsString<number>;  // "bukan string"

// Ekstrak tipe dari Promise
type Awaited<T> = T extends Promise<infer U> ? U : T;

async function fetchUser() {
  return { id: 1, name: "Budi" };
}
type UserType = Awaited<ReturnType<typeof fetchUser>>;
// { id: number; name: string }

2. Template Literal Types

TypeScript 4.1+ mendukung template literal types — kombinasi string literal yang sangat powerful untuk mendefinisikan string patterns secara type-safe.

ts·Template Literal Types
type Direction = "top" | "right" | "bottom" | "left";
type Margin = `margin-${Direction}`;
// "margin-top" | "margin-right" | "margin-bottom" | "margin-left"

type EventName = "click" | "focus" | "blur";
type HandlerName = `on${Capitalize<EventName>}`;
// "onClick" | "onFocus" | "onBlur"

3. Discriminated Unions untuk State Management

Pola ini sangat berguna untuk mengelola state yang memiliki bentuk berbeda-beda, misalnya state API call yang bisa idle, loading, success, atau error.

tsx·Async State Pattern
type AsyncState<T> =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: T }
  | { status: "error"; error: Error };

function DataDisplay({ state }: { state: AsyncState<User[]> }) {
  switch (state.status) {
    case "idle":    return <p>Belum ada data</p>;
    case "loading": return <Spinner />;
    case "success": return <UserList users={state.data} />;
    case "error":   return <ErrorMessage msg={state.error.message} />;
  }
}

4. Satisfies Operator (TS 4.9+)

Operator satisfies memungkinkan kamu memvalidasi tipe tanpa kehilangan informasi tipe yang lebih spesifik. Ini salah satu fitur paling berguna di TypeScript modern.

ts·Satisfies vs Type Annotation
type Color = string | RGB;
type RGB = [number, number, number];

// ❌ Dengan annotation biasa — kehilangan info spesifik
const palette: Record<string, Color> = {
  red: [255, 0, 0],
  green: "#00ff00",
};
palette.red.toUpperCase(); // Error: Color mungkin bukan string

// ✅ Dengan satisfies — tipe spesifik dipertahankan!
const palette2 = {
  red: [255, 0, 0],
  green: "#00ff00",
} satisfies Record<string, Color>;

palette2.red[0];          // ✅ TypeScript tahu ini array
palette2.green.toUpperCase(); // ✅ TypeScript tahu ini string
💡 Kapan menggunakan pola ini? Advanced TypeScript patterns paling berguna saat membangun library, shared utilities, atau design systems. Jangan over-engineer tipe kamu kalau tidak memberikan value nyata.