as で型エラーを握りつぶしたら、まったく別の場所でコードが壊れた。TypeScript の satisfies 演算子を覚えると、こうした事故をその場で防げるようになります。

satisfies って結局何をする演算子なの?as や型注釈(:)で書くのと何が違うのかわからない。
: を付けると補完が効かなくなり、as を使うと間違った値も通ってしまう。安全に値を型で縛る書き方が知りたい。
as const satisfies という書き方をよく見かけるけれど、なぜこの順番なのか、何が嬉しいのかが腹落ちしていない。

satisfies は、値がある型に当てはまるかを検査しつつ、変数の型は推論された具体的なものを残してくれる演算子です。: は具体型を奪い、as は検査を奪う——この違いさえつかめば、三者の使い分けに迷わなくなります。実コードと推論結果の対比を通して、その判断基準を最後まで整理していきます。

この記事は次のような方におすすめです。

この記事はこんな人におすすめ!
  • satisfies が何をする演算子で、何が嬉しいのかを知りたい方
  • 型注釈(:)や as との違い・使い分けではっきりした基準が欲しい方
  • as const satisfies の定番パターンを仕組みから理解したい方
  • as で握りつぶしていたコードを、より安全な書き方に直したい方

読み終えるころには、設定オブジェクトや定数を「型で縛りつつ補完も推論も残す」書き方が自分で選べるようになり、as 由来の見えないバグを未然に減らせます。

それでは、順を追って詳しく見ていきましょう!

satisfies演算子とは|「検査はするが型は奪わない」

satisfies は、値がある型に代入可能かを検査するが、変数の型はその型に固定せず、推論された具体型のまま残す演算子です。型チェックの恩恵を受けながら、リテラル型やキーごとの具体的な情報を失わずに済むのが最大のうまみです。

最小の構文は 値 satisfies 型 の形で書きます。

type Config = Record<string, number | string>;

const config = {
  port: 8080,
  host: "localhost",
} satisfies Config;

// hoverで確認できる推論型:
// const config: { port: number; host: string; }
config.port; // number として扱える

ここで configConfigRecord<string, number | string>)ではなく、{ port: number; host: string } という具体的な型として推論されます。もし configConfig を型注釈で付けていたら、config.portnumber | string に広がってしまいますが、satisfies ならキーごとの具体型がそのまま保たれるわけです。

リテラル型を保ちたいケースでも効果がわかりやすく出ます。

const palette = {
  primary: "#FF0000",
  secondary: "#00FF00",
} satisfies Record<string, string>;

// 推論型:{ primary: string; secondary: string; }
// primary / secondary というキーが存在することは保持される
palette.primary; // OK・補完も効く
palette.tertiary; // エラー:存在しないプロパティ

Record<string, string> で「文字列をキーに文字列を持つ」という制約を課しながらも、primarysecondary といった実在するキーの情報は推論型に残るため、存在しないキーへのアクセスはきちんと弾かれます。これが「検査はするが型は奪わない」の正体です。

基本構文と導入バージョン(4.9以降)

構文はシンプルで、式の末尾に satisfies 型 を付けるだけです。

const a = expr satisfies SomeType;
const b = { /* ... */ } satisfies SomeType;
const c = [1, 2, 3] satisfies readonly number[];

この演算子は TypeScript 4.9 で導入された機能です。公式リリースノートでも次のように説明されています。

TypeScript developers are often faced with a dilemma: we want to ensure that some expression matches some type, but also want to keep the most specific type of that expression for inference purposes.
出典:TypeScript Release Notes「TypeScript 4.9」The satisfies Operator

導入は 4.9 以降のため、それより前のバージョンでは構文エラーになります。プロジェクトの TypeScript が古い場合は、satisfies を書く前にバージョンを上げる必要があります。

なぜ生まれたか:型注釈とasの“穴”

satisfies が必要になった理由は、型注釈(:)と as のどちらにも「片方ずつ穴がある」からです。同じ値に対して両者を並べると、それぞれの欠点が見えてきます。

type Color = { r: number; g: number; b: number };

// 型注釈:検査は効くが、推論が Color に固定され情報が消える
const c1: Color = { r: 255, g: 0, b: 0 };
// c1 は Color。これ以上の具体情報はない

// as:型をアサーション先に置き換え、検査を弱める
const c2 = { r: 255, g: 0 } as Color;
// b が無いのにエラーにならない(検査を握りつぶしている)
c2.b; // 実行時は undefined になりうる

型注釈は安全ですが、推論された具体型を捨ててしまいます。一方 as は値を保てるものの、誤った値すら通してしまうため安全網になりません。この「検査か、推論か」の二択を強いられていた状況を解消するために satisfies が登場しました。

satisfiesと他の型指定の違いを比較表で整理

三者の違いは、「型エラーを検査するか」「推論された具体型を保つか」「コンパイラの判断を上書きできるか」の3軸で整理すると一望できます。

観点 型注釈 : as(型アサーション) satisfies
型エラーの検査 あり 弱い(代入チェックを回避できるが、重ならない型は不可) あり
推論型の保持 なし(型に固定) なし(アサーション先の型に置き換わる) あり
コンパイラ判断の上書き しない する しない
実行時の影響 なし なし なし
代表的な用途 変数の型を宣言する 推論を意図的に矯正する 検査しつつ具体型を残す

ポイントは、satisfies だけが「検査あり」と「推論型の保持あり」を両立している点です。同じオブジェクトに三者を適用して、推論型がどう変わるかを並べると差が明確になります。

type Route = { path: string; method: string };

const a: Route = { path: "/", method: "GET" };
// 推論型:Route(path も method も string に広がる)

const b = { path: "/", method: "GET" } as Route;
// 推論型:Route(型が Route に置き換わる)
// もし { path: "/" } as Route のように不足があっても検査されず通ってしまう

const c = { path: "/", method: "GET" } satisfies Route;
// 推論型:{ path: string; method: string }
// Route への適合は検査されつつ、具体型は保たれる

型注釈(:)との違い:具体型が失われる

型注釈との決定的な差は、: は変数の型を指定した型そのものに固定し、キー単位の具体値情報を消してしまう点です。

const themes: Record<string, string> = {
  light: "white",
  dark: "black",
};

themes.light; // string
themes.unknown; // string(存在しないキーもエラーにならない)

型注釈で Record<string, string> を付けると、themes は「任意の文字列キーを持つ」型として扱われ、lightdark という実在キーの情報が失われます。存在しないキーへのアクセスすら通ってしまうわけです。

const themes = {
  light: "white",
  dark: "black",
} satisfies Record<string, string>;

themes.light; // string・補完が効く
themes.unknown; // エラー:存在しないプロパティ

satisfies に変えると、Record<string, string> への適合は検査しつつ、light / dark というキーの情報が残ります。「制約は課したいが、補完や具体型は残したい」場面では型注釈より satisfies が向くということです。

型アサーションとの違い:検査を上書きできる

as との決定的な違いは、as はコンパイラの検査を握りつぶし、誤った値でも通してしまう点にあります。

type User = { id: number; name: string };

const u = { id: 1 } as User;
// name が無いのにエラーにならない
console.log(u.name.toUpperCase()); // 実行時に TypeError

as は「この値はこの型だ」とコンパイラに言い切らせる演算子なので、不足など一部の不整合を通せるが、重ならない型への単発アサーションはエラーになります。同じ誤りを satisfies で書くと、その場で弾かれます。

const u = { id: 1 } satisfies User;
// 例:TS1360 Type '{ id: number; }' does not satisfy the expected type 'User'.
//     Property 'name' is missing in type '{ id: number; }' but required in type 'User'.
//     (TypeScriptバージョンにより文言が異なる場合あり)

値の型が合わない場合も同様にエラーになります。

const u = { id: "1", name: "Ann" } satisfies User;
// 例:TS2322 Type 'string' is not assignable to type 'number'.
//     (TypeScriptバージョンにより文言が異なる場合あり)

つまり as が「最終手段としてコンパイラの判断を上書きする」道具なのに対し、satisfies は判断を上書きせず、誤りを正面から検査する道具です。

なかむぅ
なかむぅ
as(型アサーション)はどんな場面で使ってよく、どこに危険があるのか。使い所と注意点をまとめた解説です。
TypeScriptのasとは?型アサーションの危険性と安全な代替TypeScriptのas(型アサーション)を実コードとtscのエラーで解説。書き方・キャストとの違い・なぜ危険かを示し、asを避ける型ガードやsatisfiesまで網羅。エラーを消すだけでなく型安全を守りたい人へ。...

as const satisfies|widening防止と検査を同時に行う定番パターン

as const satisfies T は、as const でリテラル化・readonly 化してから、satisfies T で構造を検査するという二段構えのパターンです。順序には意味があり、先に as const で型を確定させ、その確定した型を satisfies で検査します。

まず widening(型の広がり)を確認します。オブジェクトリテラルは何もしないと、各プロパティの型が広い型へ推論されます。

const env1 = { mode: "production" };
// 推論型:{ mode: string }
// "production" というリテラルが string に広がっている(widening)

as const を付けると、この widening を抑えてリテラル型と readonly を確定できます。

const env2 = { mode: "production" } as const;
// 推論型:{ readonly mode: "production" }

ここに satisfies を重ねると、リテラル型・readonly を保ったまま、型への適合も検査されるという両取りが実現します。

type Env = { mode: "production" | "development" };

const env = { mode: "production" } as const satisfies Env;
// 推論型:{ readonly mode: "production" }
// Env への適合は検査されつつ、リテラル型が保持される

const bad = { mode: "prod" } as const satisfies Env;
// 例:TS2322 Type '"prod"' is not assignable to type
//     '"production" | "development"'.
//     (TypeScriptバージョンにより文言が異なる場合あり)

順序を逆にして satisfies Env as const のように書くと意図どおりに働きません。必ず as const を先に置き、リテラル化した値を satisfies で検査するのが正しい形です。

なかむぅ
なかむぅ
as const でリテラル型を固定する仕組みと、widening を抑える考え方を基礎から整理した解説です。
TypeScriptのas const|型が広がる罠とenum代替・注意点TypeScriptのas const(constアサーション)を基礎から解説。リテラル型への変換やwidening回避、配列・オブジェクトでの書き方、enumやsatisfies・readonlyとの使い分けと落とし穴まで整理します。...

よくある適用例:設定オブジェクト・定数のexport

実務で as const satisfies が活きるのは、設定オブジェクトやルーティング定数を「型で縛りつつ、キーの補完とリテラル型は残したい」場面です。

type RouteConfig = Record<string, { path: string; auth: boolean }>;

export const routes = {
  home: { path: "/", auth: false },
  dashboard: { path: "/dashboard", auth: true },
} as const satisfies RouteConfig;

// routes.home.path は "/" というリテラル型
// routes.unknown はエラー(存在しないキー)
// 各エントリが RouteConfig の形に合うか検査される

RouteConfig で各値の構造を強制しつつ、home / dashboard というキーや "/" というパスのリテラル型がそのまま残ります。これにより、定数を export した先でもキー名の補完が効き、タイプミスは型エラーで気づけるという安全さと利便性を同時に得られます。

いつsatisfiesを使う?判断フローと注意点

三者の選択は、「推論された具体型を後で使うか」を起点に判断すると迷いません。

  • 値の具体型を後で使う(補完・リテラル型を残したい)→ satisfies(必要なら as const を併用)
  • 単に変数の型を宣言したいだけ → 型注釈 :
  • コンパイラの判断を上書きしたい(最終手段)→ as

このうち日常的に選ぶべき第一候補は satisfies です。型注釈は型を固定したいときに、as はやむを得ず推論を矯正するときに限って使う、と位置づけると整理できます。

注意点として最も重要なのは、satisfies は型レベルでしか働かず、実行時には何もしないことです。satisfies を含むコードはコンパイル後に消えるため、外部から来る JSON やフォーム入力のように実行時に値の正しさを保証したい場合は、別途バリデーションが必要です。

// satisfies はコンパイル時の検査のみ
const data = JSON.parse(input) satisfies User;
// 実行時に input が User である保証はない

実行時の値検証まで担保したいときは、スキーマ検証ライブラリと組み合わせるのが定石です。

そのほか、satisfies4.9 以降でしか使えない点と、有限のキー集合を持つ型にオブジェクトリテラルを直接 satisfies させる場合は、型にないキー(過剰なプロパティ)を検出できる点も押さえておくとよいですよ。

よくある質問

Q1. satisfiesと型注釈(:)はどちらを使うべき?

推論された具体型を後段で使うなら satisfies を選びます。キー名の補完やリテラル型を保ったまま、型への適合だけ検査できるためです。一方、単に変数の型を宣言したいだけで具体型が不要なら、型注釈 : で十分です。「具体型を残したいか」が分かれ目になります。

Q2. satisfiesは実行時に型チェックしてくれる?

いいえ、satisfies は型レベルの検査のみで、コンパイル後のコードには残りません。実行時には何の検証も行わないため、外部入力など実行時に値の正しさを保証したい場合は、zod などのスキーマ検証ライブラリを使う必要があります。

Q3. satisfiesが使えない(エラーになる)のはなぜ?

satisfies は TypeScript 4.9 で導入されたため、4.9 未満では構文エラーになります。使えないときは、まず利用中の TypeScript バージョンを確認してください。バージョンが古ければアップデートで解決します。

Q4. as const satisfies と satisfies as const のどちらが正しい?

as const satisfies T の順が正しい書き方です。先に as const でリテラル化・readonly 化して型を確定させ、その確定した型を satisfies T が検査するという流れになります。逆順では意図どおりに働きません。

【付録】さらに学びを深めるためのリソース


さらにTypescriptの学習を進めたい方のために、いくつかのリソースを紹介します。
これらのリソースを活用することで、TypeScriptの型システムについてより深い知識を得ることができるでしょう。

おすすめの書籍

ゼロからわかる TypeScript入門


技術評論社から出版されている「ゼロからわかる TypeScript入門」は、プログラミング初心者や本職プログラマーではない方を主な対象にした入門書です。

変数・条件分岐・ループといった基本から、クラスやインターフェース、モジュールまで段階的に学べる構成になっています。最終章ではWeb APIとJSONを使った非同期Webアプリの作成も体験できるので、「実際に動くものを作る」ところまで到達できます。

プロを目指す人のためのTypeScript入門


技術評論社の「プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで」、通称 ブルーベリー本 です。
JavaScriptの仕様とTypeScript独自の機能を両方押さえつつ、リテラル型・ユニオン型・keyof型・ジェネリクスなど、高度な型表現まで踏み込んで解説しています。TypeScriptの型システムの表現力を本格的に学べる一冊です。

オンラインで参照できる公式ドキュメント

TypeScript公式ハンドブック


https://www.typescriptlang.org/docs/
TypeScriptの公式ドキュメントです。
intersection型を含む、すべての型システムの機能について詳細な説明があります。

TypeScript Deep Dive


https://basarat.gitbook.io/typescript/
TypeScriptの深い部分まで掘り下げて解説しているオンラインブックです。
無料で読むことができ、intersection型についても詳しく説明されています。

TypeScriptの学習は終わりがありません。
新しい機能が常に追加され、より良い書き方が発見されています。
継続的に学習を続けることで、より良いTypeScriptプログラマーになれるはずです。


まとめ – satisfiesは検査するが型は奪わない

この記事では、satisfies 演算子と型注釈・as の使い分けを整理しました。

  • satisfies は値を型で検査するが、推論された具体型は奪わない
  • : は具体型を奪い、as は検査を奪う——この対比が選択の軸
  • 具体型を後で使うなら satisfies、宣言だけなら :、上書きが要るなら最終手段の as
  • as const satisfies T は widening 防止と検査を両立する定番パターン(順序は as const が先)
  • satisfies は型レベルのみで、実行時には何もしない

「検査はするが型は奪わない」という一点を覚えておけば、設定オブジェクトや定数を安全かつ便利に縛れるようになります。

なかむぅ
なかむぅ
as(型アサーション)の使い所と危険性を、具体例とともに整理した解説です。satisfies との対比をさらに深めたい方はこちら。
TypeScriptのasとは?型アサーションの危険性と安全な代替TypeScriptのas(型アサーション)を実コードとtscのエラーで解説。書き方・キャストとの違い・なぜ危険かを示し、asを避ける型ガードやsatisfiesまで網羅。エラーを消すだけでなく型安全を守りたい人へ。...
なかむぅ
なかむぅ
as const とリテラル型・widening の仕組みを基礎から押さえると、as const satisfies の理解が一段深まります。
TypeScriptのas const|型が広がる罠とenum代替・注意点TypeScriptのas const(constアサーション)を基礎から解説。リテラル型への変換やwidening回避、配列・オブジェクトでの書き方、enumやsatisfies・readonlyとの使い分けと落とし穴まで整理します。...

※本記事の本文案はAIを活用して作成していますが、記載している内容およびコードは筆者が実際に調査、検証・実行し、内容の正確性を確認した上で公開しています。