🦢swan's room
2026.02.05TypeScript

satisfiesとasの使い分けを理解する

はじめに

TypeScript 4.9 で導入された satisfies 演算子は、型の安全性を保ちながら値の型推論を維持できる強力な機能です。

既存の as との違いを正しく理解し、使い分けることが重要です。

as の問題点

as はダウンキャストもアップキャストも許容するため、型安全性が失われるケースがあります。

type Color = "red" | "green" | "blue";

// as を使うと、誤った値でもコンパイルが通ってしまう
const palette = {
  red: [255, 0, 0],
  green: "#00ff00",
  blue: [0, 0, 255],
} as Record<Color, string | number[]>;

// palette.green の型は string | number[] になる
// 実際は string なのに number[] のメソッドも呼べてしまう

satisfies の登場

satisfies は「この値が型を満たすかチェックするが、推論された型はそのまま保持する」という動作をします。

type Color = "red" | "green" | "blue";

const palette = {
  red: [255, 0, 0],
  green: "#00ff00",
  blue: [0, 0, 255],
} satisfies Record<Color, string | number[]>;

// palette.green の型は string(推論が保持される)
palette.green.toUpperCase(); // ✅ OK

// palette.red の型は number[](推論が保持される)
palette.red.map((v) => v * 2); // ✅ OK

実務での使い分け

satisfies を使うべきケース

  1. 設定オブジェクトの型チェック
type Config = {
  apiUrl: string;
  timeout: number;
  retries: number;
};

export const config = {
  apiUrl: "https://api.example.com",
  timeout: 5000,
  retries: 3,
} satisfies Config;

// config.apiUrl は "https://api.example.com" リテラル型
  1. Record のキー網羅チェック
type Status = "idle" | "loading" | "success" | "error";

const statusLabel = {
  idle: "待機中",
  loading: "読み込み中",
  success: "完了",
  error: "エラー",
} satisfies Record<Status, string>;
// キーが足りないとコンパイルエラー

as を使うべきケース

  1. DOM 要素の型アサーション
const input = document.getElementById("email") as HTMLInputElement;
  1. API レスポンスの型付け(ただしバリデーションと併用すべき)
const data = (await res.json()) as ApiResponse;

まとめ

| 観点 | as | satisfies | |------|------|-------------| | 型チェック | 弱い(強制キャスト) | 強い(型を満たすか検証) | | 推論の保持 | 失われる | 保持される | | 主な用途 | DOM操作、外部データ | 設定、定数定義 |

基本方針として、まず satisfies を検討し、as は型推論が不可能な場面でのみ使うのがおすすめです。