TypeScript Systems ⏱️ 7 分鐘閱讀

TypeScript 高階元程式設計與型別推導實戰

利用型別系統進行編譯期邏輯驗證,打造零 Runtime 效能損耗的全型別安全 API 系統。

1. 什麼是型別元程式設計?

TypeScript 的型別系統本身是 **Turing-complete (圖靈完備)** 的。這意味著我們可以在「編譯期 (Compile Time)」執行強大的型別層級運算,將常見的 Runtime 錯誤攔截在開發階段。

2. Conditional Types 與 infer 實戰

透過 infer 關鍵字,我們可以輕鬆拆解非同步 Promise 或解構 API 的回應型別:

// 自動解構 Promise 或回傳非 Promise 原始型別
type UnwrapPromise = T extends Promise ? UnwrapPromise : T;

type AsyncData = Promise>;
type RealData = UnwrapPromise; // { id: string; name: string }

3. Template Literal Types 模板字面量型別

結合字串範本,可以在型別層級自動檢查 API 路由格式:

type EventName = 'click' | 'hover';
type Component = 'button' | 'card';

// 自動推導為 'button:click' | 'button:hover' | 'card:click' | 'card:hover'
type ActionEvent = `${Component}:${EventName}`;

4. 型別安全 API Client 建構實戰

以下示範如何在前端與後端共用型別契約時,打造擁有 IntelliSense 自動補全的 API Client:

interface APIContract {
  'GET /api/v1/users': { response: { id: number; name: string }[] };
  'POST /api/v1/users': { body: { name: string }; response: { id: number } };
}

async function fetchAPI(
  endpoint: K,
  options?: APIContract[K] extends { body: infer B } ? { body: B } : undefined
): Promise {
  const [method, path] = endpoint.split(' ');
  const res = await fetch(path, {
    method,
    headers: { 'Content-Type': 'application/json' },
    body: options?.body ? JSON.stringify(options.body) : undefined
  });
  return res.json();
}

// 擁有全型別自動補全!
const users = await fetchAPI('GET /api/v1/users');

5. 常見問題解答 (FAQ)

Q: TypeScript 中的 infer 關鍵字在何時使用?

infer 用於條件型別 (Conditional Types) 之中,能在編譯期動態解構並提取函式回傳值、Promise 包裝內容或陣列元素的真實型別。