TypeScriptで型安全なコードを書くための5つのTips

TypeScript
フロントエンド
開発Tips
TypeScriptの型システムを活用して、より安全で保守性の高いコードを書くためのテクニックを紹介します。
作者

山田太郎

公開

2024年1月15日

はじめに

TypeScriptを使っていると、型の恩恵を最大限に活かせていないケースをよく見かけます。 今回は、実務で役立つ型安全なコードを書くためのTipsを5つ紹介します。

1. Union型とType Guardの活用

type Status = 'loading' | 'success' | 'error';

interface LoadingState {
  status: 'loading';
}

interface SuccessState {
  status: 'success';
  data: string[];
}

interface ErrorState {
  status: 'error';
  message: string;
}

type State = LoadingState | SuccessState | ErrorState;

function handleState(state: State) {
  switch (state.status) {
    case 'loading':
      return 'Loading...';
    case 'success':
      return state.data.join(', '); // dataに安全にアクセス
    case 'error':
      return `Error: ${state.message}`; // messageに安全にアクセス
  }
}

2. Genericsで再利用可能な型を作る

// APIレスポンスの汎用型
interface ApiResponse<T> {
  data: T;
  status: number;
  timestamp: Date;
}

// 使用例
interface User {
  id: number;
  name: string;
}

async function fetchUser(id: number): Promise<ApiResponse<User>> {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
}

3. Const Assertionでリテラル型を保持

// asConst なし - string[]として推論される
const colors = ['red', 'green', 'blue'];

// as const あり - readonly ['red', 'green', 'blue']として推論される
const colorsConst = ['red', 'green', 'blue'] as const;

// 型として使用可能
type Color = typeof colorsConst[number]; // 'red' | 'green' | 'blue'

4. Template Literal Typesの活用

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Endpoint = '/users' | '/posts' | '/comments';

// 組み合わせた型を自動生成
type ApiRoute = `${HttpMethod} ${Endpoint}`;
// 'GET /users' | 'GET /posts' | 'GET /comments' | 'POST /users' | ...

function request(route: ApiRoute) {
  // 型安全なルーティング
}

request('GET /users'); // OK
request('PATCH /users'); // エラー

5. Utility Typesを使いこなす

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
  createdAt: Date;
}

// 更新用の型(すべてオプショナル)
type UpdateUser = Partial<User>;

// 表示用の型(パスワードを除外)
type PublicUser = Omit<User, 'password'>;

// 必須フィールドのみの型
type RequiredUserFields = Pick<User, 'id' | 'name' | 'email'>;

// 読み取り専用
type ReadonlyUser = Readonly<User>;

まとめ

TypeScriptの型システムは非常に強力です。 これらのテクニックを活用することで、コンパイル時にバグを発見し、より保守性の高いコードを書くことができます。

ヒント次のステップ

TypeScript公式ドキュメントのAdvanced Typesを読んで、さらに深く学びましょう。