satisfies は、TypeScript 4.9 で入った演算子です。式の型がある型に合っているかを確かめますが、その式の型は変えません。型注釈(const palette: 型 = …)は、変数の型が注釈の型になるので、プロパティごとの細かい型が無くなります。as(型アサーション)は、TypeScript には分からない型を自分が知っているときに、型を指定するものです。足りないプロパティがあってもエラーになりませんでした(試した結果)。ただし、型どうしが十分に重ならないときは、as でも TS2352 で止まります。
使いどころは、公式の文書では次のように分かれています。satisfies は、型に合っているかを確かめたいけれど、推論(TypeScript が、書いた値から型を自動で決めること)で決まった細かい型も残したい、というときのためのものです(4.9 のリリースノート)。型注釈は、たいていは付けなくてよく、TypeScript が初期値から型を推論します(Handbook)。as は、document.getElementById("main_canvas") as HTMLCanvasElement のように、TypeScript には分からない型を自分が知っているときに使います(Handbook)。
TypeScript 4.9 のリリースノートと同じ形の palette を、型注釈・as・satisfies の 3 通りで書いて tsc で調べると、型注釈と as は palette.green.toUpperCase() で TS2339(string | RGB に toUpperCase が無い)になり、satisfies だけがエラーになりませんでした。satisfies のときの palette.green は string、palette.red は [number, number, number](数が 3 つ並ぶ配列の型)でした。どちらも、number に代入したときのエラーの文に出た型です。
型注釈・as・satisfies を同じコードで調べた結果を、1 つの表にまとめます(TypeScript 7.0.2。型は、number に代入したときのエラーの文に出たものです)。a1〜f4 は、後ろの節で使うコードの名前です。流していない組み合わせは「流していない」と書きました。
| 調べたこと | 型注釈 | as | satisfies |
|---|---|---|---|
palette.green.toUpperCase()(a1〜a3) | TS2339 | TS2339 | エラーなし |
palette.green の型(a1〜a3) | string または RGB | string または RGB | string |
palette.red の型(a1〜a3) | string または RGB | string または RGB | [number, number, number] |
足りないプロパティ(blue なし。c1〜c3) | TS2741(2 行 7 列) | エラーなし | TS2741(5 行 3 列) |
余分なプロパティ(bleu と blue なし。d1〜d3) | TS2353 | TS2352 | TS2353 |
余分なプロパティだけ(colour。f3) | 流していない | エラーなし | TS2561 |
値の型が合わない(port: "8080"。f4) | 流していない | TS2352 | TS2322 |
比べに使うコードは、次の 2 つのファイルです。types.ts に型を置き、a3-satisfies.ts が satisfies で書いたものです。
types.ts:
export type Colors = "red" | "green" | "blue";
export type RGB = [red: number, green: number, blue: number];
a3-satisfies.ts:
import type { Colors, RGB } from "./types.ts";
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255],
} satisfies Record<Colors, string | RGB>;
const greenNormalized = palette.green.toUpperCase();
const n1: number = palette.green;
const n2: number = palette.red;
最後の 2 行(n1・n2 の 8・9 行目)は、推論された型を見るためにわざとエラーにした行です。number に代入できないという文に、その式の型が出ます。
打つ形は次のとおりです。typescript を入れたフォルダーで流します。
npm install -D typescript@7.0.2
npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions a3-satisfies.ts
npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja a3-satisfies.ts
--allowImportingTsExtensions は、types.ts から型を読み込むために付けました。tsconfig.json は置いていません。
satisfies(a3)の出力は次のとおりです(TypeScript 7.0.2、--locale なし)。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions a3-satisfies.ts
a3-satisfies.ts(8,7): error TS2322: Type 'string' is not assignable to type 'number'.
a3-satisfies.ts(9,7): error TS2322: Type '[number, number, number]' is not assignable to type 'number'.
型注釈(a1)と as(a2)のコードと出力は、下の「同じコードで比べる」にあります。
satisfiesが何をするか(4.9 のリリースノートの定義)と、エラーの全文(英語と--locale ja)- 型注釈・
as・satisfiesを同じコードで比べた tsc の出力 - 足りない・余分・型が違うときのエラーの番号(7.0.2 と 6.0.3 で違ったところも)
as const satisfiesの書き方と、順番を逆にしたときの TS1355
確かめた環境は、TypeScript 7.0.2 と 6.0.3(エラーの文は、足りないプロパティのときを除いて同じ。終了コードは 7.0.2 が 1、6.0.3 が 2)・Node.js 24.22.1 です。Docker の Linux で、2026年10月23日に流しました。Windows と macOS では流していません。
satisfies とは?
TypeScript のリリースノートは、開発者がよく次の板挟みにあうと書いています。式がある型に合っていることを確かめたい。でも、推論のために、その式のいちばん細かい型も残したい、という二つです。
satisfies は、この板挟みのために TypeScript 4.9 で入った演算子です。リリースノートの定義は、式の型がある型に合っているかを確かめる。ただし、その式の結果の型は変えない、というものです。リリースノートの例では、} satisfies Record<Colors, string | RGB>; と書くと、綴りの誤り(bleu)は見つかり、palette.green.toUpperCase() も使えます。
エラーの全文(英語と --locale ja)
文字列や数の値に satisfies を付けたコードで調べます。3 行目は型に合わない文字列、4 行目は string に合わない数です。5 行目は、message を number に代入しようとしたわざと書いた行で、この行のエラーの文に出る型は、message の型の説明には使いません。
type WelcomeMessage = "hello world" | "Hello, world";
const message = "hello world" satisfies WelcomeMessage;
const failingMessage = "Hello world!" satisfies WelcomeMessage;
const port = 8080 satisfies string;
const n: number = message;
TypeScript 7.0.2 の出力です(6.0.3 も同じでした)。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions b2-primitive.ts
b2-primitive.ts(3,39): error TS1360: Type '"Hello world!"' does not satisfy the expected type 'WelcomeMessage'.
b2-primitive.ts(4,19): error TS1360: Type 'number' does not satisfy the expected type 'string'.
b2-primitive.ts(5,7): error TS2322: Type 'string' is not assignable to type 'number'.
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja b2-primitive.ts
b2-primitive.ts(3,39): error TS1360: 型 '"Hello world!"' は想定された型 'WelcomeMessage' を満たしていません。
b2-primitive.ts(4,19): error TS1360: 型 'number' は想定された型 'string' を満たしていません。
b2-primitive.ts(5,7): error TS2322: 型 'string' を型 'number' に割り当てることはできません。
TS1360 は、2 行目のように型に合っているときは出ません。合っているときの message の型は、別のコードで調べました。"hello world" を "hello world" の型の変数に入れる 3 行目は通り、"Hello, world" の型の変数に入れる 4 行目だけが止まります。
type WelcomeMessage = "hello world" | "Hello, world";
const message = "hello world" satisfies WelcomeMessage;
const ok: "hello world" = message;
const ng: "Hello, world" = message;
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions b3-primitive-literal.ts
b3-primitive-literal.ts(4,7): error TS2322: Type '"hello world"' is not assignable to type '"Hello, world"'.
エラーの文に "hello world" と出ているので、message の型は "hello world" です。string のような大まかな型ではなく、その値の型です(リテラル型と呼びます)。satisfies を付けても、式の型は WelcomeMessage には広がりませんでした。
JSDoc の @satisfies(5.0 から)
JavaScript のファイルでは、JSDoc のタグ @satisfies が、satisfies と同じ働きをします。TypeScript の文書は、値がある型を満たすと宣言するが、値の型は変えないものだと説明しています。この JSDoc のタグは、TypeScript 5.0 から使えます。
satisfies と as・型注釈の違い
型を決める書き方は、型注釈・as・satisfies の 3 つがあります。それぞれが何をするかを順に見て、最後に同じコードで比べます。
型注釈とは
型注釈は、const・var・let で変数を宣言するときに、変数の型を明示するものです。付けなくてもかまいません。型注釈は、型を付けるものの後ろに書きます。
let myName: string = "Alice";
TypeScript の Handbook は、たいていは型注釈は要らないと書いています。TypeScript はできるかぎり型を推論し、変数の型は初期値の型から推論されるためです。
型注釈を付けると、変数の型は注釈の型になります。リリースノートの例では、palette に Record<Colors, string | RGB> の型注釈を付けると、綴りの誤りは見つかりますが、プロパティごとの情報が無くなります。そのため、palette.green.toUpperCase() が「string | RGB に toUpperCase が無い」というエラーになります。手元でも、同じ形のエラーになりました(下の「同じコードで比べる」の a1)。
as(型アサーション)とは
as は、TypeScript が知りえない型の情報を自分が知っているときに、より細かい型を指定するものです。Handbook の例は、次のとおりです。
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
型注釈と同じく、型アサーションはコンパイラが取り除き、実行時の動きは変わりません。Handbook は、実行時のチェックは無く、アサーションが間違っていても例外も null も出ない、と書いています。
.tsx 以外のファイルなら、山かっこの書き方(<HTMLCanvasElement>…)も同じ意味です。.tsx では山かっこの書き方は使えません。.ts と .tsx など、ファイルの種類の違いは、.js .jsx .ts .tsx の違いの記事で説明しています。
as は、何でも別の型にできるわけではありません。Handbook によると、as が許すのは、より細かい型か、より大まかな型への変換だけです。"hello" as number のような無理な変換は、TS2352 で止まります。エラーの文は、まず式を unknown に変換するよう案内しています。
同じコードで比べる(tsc の出力)
リリースノートと同じ形の palette を、型注釈(a1)・as(a2)・satisfies(a3)・何も付けない(a4)で書きました。types.ts と a3 は、冒頭のとおりです。型注釈・as・satisfies の結果は、冒頭の表にまとめました。
import type { Colors, RGB } from "./types.ts";
const palette: Record<Colors, string | RGB> = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255],
};
const greenNormalized = palette.green.toUpperCase();
const n1: number = palette.green;
const n2: number = palette.red;
上が a1(型注釈)です。a2(as)は、palette の宣言だけが違います。
import type { Colors, RGB } from "./types.ts";
const palette = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255],
} as Record<Colors, string | RGB>;
const greenNormalized = palette.green.toUpperCase();
const n1: number = palette.green;
const n2: number = palette.red;
a1 と a2 の出力です(TypeScript 7.0.2、--locale なし)。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions a1-annotation.ts
a1-annotation.ts(7,39): error TS2339: Property 'toUpperCase' does not exist on type 'string | RGB'.
Property 'toUpperCase' does not exist on type 'RGB'.
a1-annotation.ts(8,7): error TS2322: Type 'string | RGB' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
a1-annotation.ts(9,7): error TS2322: Type 'string | RGB' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions a2-as.ts
a2-as.ts(7,39): error TS2339: Property 'toUpperCase' does not exist on type 'string | RGB'.
Property 'toUpperCase' does not exist on type 'RGB'.
a2-as.ts(8,7): error TS2322: Type 'string | RGB' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
a2-as.ts(9,7): error TS2322: Type 'string | RGB' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
何も付けないコード(a4)も流しました。a4 は、冒頭の表には入れていません。number に代入したときのエラーの文では、palette.green は string、palette.red は number[] でした。
satisfies のときの red は [number, number, number] で、何も付けないときの number[] と違いました。違いの事実だけを書いています。理由を書いた公式の文は、見つけていません。
--locale ja を付けたときの TS2339 の文です(a1。TypeScript 7.0.2)。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja a1-annotation.ts
a1-annotation.ts(7,39): error TS2339: プロパティ 'toUpperCase' は型 'string | RGB' に存在しません。
プロパティ 'toUpperCase' は型 'RGB' に存在しません。
6.0.3 でも、a1〜a4 の文は同じでした。
型に合わないときに出るエラー
型に合わない式に satisfies を付けたときの出方を、値の型が違う・プロパティが足りない・プロパティが余分、の 3 つで見ます。出力は TypeScript 7.0.2 のものです。
値の型が違う(TS2322)
green に数、blue に要素が 2 つの配列を書いたコードです。
import type { Colors, RGB } from "./types.ts";
const palette = {
red: [255, 0, 0],
green: 0x00ff00,
blue: [0, 0],
} satisfies Record<Colors, string | RGB>;
エラーは、そのプロパティの行に出ます。要素が 2 つの配列は、「2 個あるが 3 個要る」というところまで出ました(6.0.3 も同じ文でした)。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions b1-wrongtype.ts
b1-wrongtype.ts(4,3): error TS2322: Type 'number' is not assignable to type 'string | RGB'.
b1-wrongtype.ts(5,3): error TS2322: Type '[number, number]' is not assignable to type 'string | RGB'.
Type '[number, number]' is not assignable to type 'RGB'.
Source has 2 element(s) but target requires 3.
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja b1-wrongtype.ts
b1-wrongtype.ts(4,3): error TS2322: 型 'number' を型 'string | RGB' に割り当てることはできません。
b1-wrongtype.ts(5,3): error TS2322: 型 '[number, number]' を型 'string | RGB' に割り当てることはできません。
型 '[number, number]' を型 'RGB' に割り当てることはできません。
ソースには 2 個の要素が含まれていますが、ターゲットには 3 個が必要です。
プロパティが足りない(TS2741)
blue を書かなかったコードです。c1 が satisfies で、下の枠がそのコードです。c2 は 2 行目が型注釈、c3 は 5 行目が as で、残りの行は c1 と同じです。
import type { Colors, RGB } from "./types.ts";
const palette = {
red: [255, 0, 0],
green: "#00ff00",
} satisfies Record<Colors, string | RGB>;
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions c1-missing-satisfies.ts
c1-missing-satisfies.ts(5,3): error TS2741: Property 'blue' is missing in type '{ red: [number, number, number]; green: string; }' but required in type 'Record<Colors, string | RGB>'.
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions c2-missing-annotation.ts
c2-missing-annotation.ts(2,7): error TS2741: Property 'blue' is missing in type '{ red: [number, number, number]; green: string; }' but required in type 'Record<Colors, string | RGB>'.
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions c3-missing-as.ts
satisfies(c1)と型注釈(c2)は、どちらも TS2741 で止まりました。エラーの場所が違い、satisfies は 5 行 3 列(satisfies と書いた位置)、型注釈は 2 行 7 列(変数名の位置)です。as(c3)はエラーが出ず、終了コードは 0 でした。
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja c1-missing-satisfies.ts
c1-missing-satisfies.ts(5,3): error TS2741: プロパティ 'blue' は型 '{ red: [number, number, number]; green: string; }' にありませんが、型 'Record<Colors, string | RGB>' では必須です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja c2-missing-annotation.ts
c2-missing-annotation.ts(2,7): error TS2741: プロパティ 'blue' は型 '{ red: [number, number, number]; green: string; }' にありませんが、型 'Record<Colors, string | RGB>' では必須です。
余分なプロパティ(TS2353)
blue の綴りを間違えて bleu と書いたコードです。d1 が satisfies で、下の枠がそのコードです。d2 は 2 行目が型注釈、d3 は 6 行目が as で、残りの行は d1 と同じです。
import type { Colors, RGB } from "./types.ts";
const palette = {
red: [255, 0, 0],
green: "#00ff00",
bleu: [0, 0, 255],
} satisfies Record<Colors, string | RGB>;
satisfies(d1)と型注釈(d2)は、同じ TS2353 で、同じ 5 行 3 列に出ました。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions d1-excess-satisfies.ts
d1-excess-satisfies.ts(5,3): error TS2353: Object literal may only specify known properties, and 'bleu' does not exist in type 'Record<Colors, string | RGB>'.
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions d2-excess-annotation.ts
d2-excess-annotation.ts(5,3): error TS2353: Object literal may only specify known properties, and 'bleu' does not exist in type 'Record<Colors, string | RGB>'.
as(d3)は、この例では TS2352「変換は誤りかもしれない」で止まりました。blue が無く bleu がある形が、Record<Colors, string | RGB> と十分に重ならないためと、エラーの文に出ています。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions d3-excess-as.ts
d3-excess-as.ts(2,17): error TS2352: Conversion of type '{ red: [number, number, number]; green: string; bleu: number[]; }' to type 'Record<Colors, string | RGB>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Property 'blue' is missing in type '{ red: [number, number, number]; green: string; bleu: number[]; }' but required in type 'Record<Colors, string | RGB>'.
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja d1-excess-satisfies.ts
d1-excess-satisfies.ts(5,3): error TS2353: オブジェクト リテラルは既知のプロパティのみ指定できます。'bleu' は型 'Record<Colors, string | RGB>' に存在しません。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja d3-excess-as.ts
d3-excess-as.ts(2,17): error TS2352: 型 '{ red: [number, number, number]; green: string; bleu: number[]; }' から型 'Record<Colors, string | RGB>' への変換は、互いに十分に重複できないため間違っている可能性があります。意図的にそうする場合は、まず式を 'unknown' に変換してください。
プロパティ 'blue' は型 '{ red: [number, number, number]; green: string; bleu: number[]; }' にありませんが、型 'Record<Colors, string | RGB>' では必須です。
Handbook は、オブジェクトリテラルは余分なプロパティのチェックを受け、そのチェックをすり抜けるいちばん簡単な方法は型アサーションだ、と書いています。例の SquareConfig は、プロパティがどれも省略できる型です。この型で colour(color の綴りの誤り)を書いたコードで調べました。5 行目が as、6 行目が satisfies です。
interface SquareConfig {
color?: string;
width?: number;
}
const a = { colour: "red", width: 100 } as SquareConfig;
const b = { colour: "red", width: 100 } satisfies SquareConfig;
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions f3-as-excess.ts
f3-as-excess.ts(6,13): error TS2561: Object literal may only specify known properties, but 'colour' does not exist in type 'SquareConfig'. Did you mean to write 'color'?
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja f3-as-excess.ts
f3-as-excess.ts(6,13): error TS2561: オブジェクト リテラルで指定できるのは既知のプロパティのみですが、'colour' は型 'SquareConfig' に存在しません。書こうとしたのは 'color' ですか?
5 行目の as にはエラーが出ず、6 行目の satisfies が TS2561(「color のつもりですか」つき)で止まりました。7.0.2 と 6.0.3 で同じ文でした。この例(プロパティがどれも省略できる型)では、as は余分なプロパティの colour を通しました。d3 のように足りないプロパティもあると、as でも止まりました。
7.0.2 と 6.0.3 で違ったところ(試した結果)
エラーの文が 7.0.2 と 6.0.3 で違ったのは、satisfies で足りないプロパティがあるとき(c1 と、あとで出る f2)だけでした。7.0.2 は TS2741 だけで、6.0.3 は TS1360 の下に同じ TS2741 の文が出ます。理由は、確かめていません。c1 を 6.0.3 で調べると、5 行 3 列に TS1360 が出て、その下の行に 7.0.2 と同じ TS2741 の文が出ました。
エラーがあるときの終了コードも、7.0.2 は 1、6.0.3 は 2 でした。7.0 と 6.0 の違いは、TypeScript 7 の記事にあります。7.0 で satisfies の扱いが変わったかどうか、番号が違う理由は、確かめていません。
as では通るのに satisfies では止まる例
host が必須の Config に、port だけの値を渡す例です。f1 は as、f2 は satisfies で書きました。
type Config = { port: number; host: string };
const config = { port: 8080 } as Config;
console.log(config.host.toUpperCase());
type Config = { port: number; host: string };
const config = { port: 8080 } satisfies Config;
console.log(config.host.toUpperCase());
f1(as)はエラーが出ず、終了コードは 0 でした。3 行目の config.host.toUpperCase() も通ります(7.0.2 と 6.0.3 とも)。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions f1-as-misses.ts
f2(satisfies)は、2 行目で host が無いことで止まります。さらに 3 行目では、config の型が { port: number; } のままなので、config.host が TS2339 になります。次は TypeScript 7.0.2 の出力です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions f2-satisfies-catches.ts
f2-satisfies-catches.ts(2,31): error TS2741: Property 'host' is missing in type '{ port: number; }' but required in type 'Config'.
f2-satisfies-catches.ts(3,20): error TS2339: Property 'host' does not exist on type '{ port: number; }'.
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja f2-satisfies-catches.ts
f2-satisfies-catches.ts(2,31): error TS2741: プロパティ 'host' は型 '{ port: number; }' にありませんが、型 'Config' では必須です。
f2-satisfies-catches.ts(3,20): error TS2339: プロパティ 'host' は型 '{ port: number; }' に存在しません。
6.0.3 では、2 行目が TS1360 になり、その下に同じ TS2741 の文が出ました。3 行目の TS2339 は同じです。
as で通った f1 を動かすと、実行時に止まります。as は実行時のチェックをしないためです(Handbook の説明)。Node.js 24.22.1 で、tsc を通さずに node f1-as-misses.ts と動かしました。.ts を Node.js で動かす話は、npx tsx の記事にあります。次の出力は、at … で始まるスタックの行 8 行を取り除いたものです。
$ node f1-as-misses.ts
file:///work/t7.0.2/f1-as-misses.ts:3
console.log(config.host.toUpperCase());
^
TypeError: Cannot read properties of undefined (reading 'toUpperCase')
Node.js v24.22.1
終了コードは 1 でした。
as でも止まる場合もあります。値の型がまったく合わない port: "8080" を、f4 で as(2 行目)と satisfies(3 行目)に渡しました。as は TS2352、satisfies は TS2322 で止まります(7.0.2 と 6.0.3 で同じ文)。
type Config = { port: number; host: string };
const c1 = { port: "8080", host: "localhost" } as Config;
const c2 = { port: "8080", host: "localhost" } satisfies Config;
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions f4-as-wrongtype.ts
f4-as-wrongtype.ts(2,12): error TS2352: Conversion of type '{ port: string; host: string; }' to type 'Config' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Types of property 'port' are incompatible.
Type 'string' is not comparable to type 'number'.
f4-as-wrongtype.ts(3,14): error TS2322: Type 'string' is not assignable to type 'number'.
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja f4-as-wrongtype.ts
f4-as-wrongtype.ts(2,12): error TS2352: 型 '{ port: string; host: string; }' から型 'Config' への変換は、互いに十分に重複できないため間違っている可能性があります。意図的にそうする場合は、まず式を 'unknown' に変換してください。
プロパティ 'port' の型に互換性がありません。
型 'string' は型 'number' と比較できません。
f4-as-wrongtype.ts(3,14): error TS2322: 型 'string' を型 'number' に割り当てることはできません。
as const satisfies の書き方と順番
as const の基本は、別の記事に書きました(→ 【TypeScript入門】型の自動拡張 wideningの防止と基礎)。
Handbook によると、as const はオブジェクト全体をリテラル型にするものです。const のように型の世界で働き、すべてのプロパティに string や number ではなく、その値の型(リテラル型)が付きます。
書き方は、{ … } as const satisfies 型 の順です。routes に as const satisfies Record<string, string> を付けた e1 を調べます。6 行目は、読み取り専用のプロパティに代入するわざと書いた行です。5 行目は number への代入で、ここに出る型は home の型の説明には使いません。
const routes = {
home: "/",
about: "/about",
} as const satisfies Record<string, string>;
const n: number = routes.home;
routes.home = "/top";
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions e1-asconst-satisfies.ts
e1-asconst-satisfies.ts(5,7): error TS2322: Type 'string' is not assignable to type 'number'.
e1-asconst-satisfies.ts(6,8): error TS2540: Cannot assign to 'home' because it is a read-only property.
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja e1-asconst-satisfies.ts
e1-asconst-satisfies.ts(5,7): error TS2322: 型 'string' を型 'number' に割り当てることはできません。
e1-asconst-satisfies.ts(6,8): error TS2540: 読み取り専用プロパティであるため、'home' に代入することはできません。
as const satisfies は通り、代入は TS2540(読み取り専用)で止まりました。home の型は、g1 で見ます。5 行目の "/" の型の変数には代入でき、6 行目の "/top" の型の変数には代入できません。エラーの文の型が "/" なので、home の型は "/" です。
const routes = {
home: "/",
about: "/about",
} as const satisfies Record<string, string>;
const h: "/" = routes.home;
const t: "/top" = routes.home;
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions g1-asconst-satisfies-literal.ts
g1-asconst-satisfies-literal.ts(6,7): error TS2322: Type '"/"' is not assignable to type '"/top"'.
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja g1-asconst-satisfies-literal.ts
g1-asconst-satisfies-literal.ts(6,7): error TS2322: 型 '"/"' を型 '"/top"' に割り当てることはできません。
as const を外して satisfies だけにすると、読み取り専用にならず、home は string でした。e3 は、e1 から as const を外したコードです。エラーは 5 行目の 1 つだけで、6 行目の routes.home = "/top"; にはエラーが出ませんでした。
g2 は、satisfies だけのコードで、home を "/" の型の変数に代入したものです。Type 'string' のエラーになります。
const routes = {
home: "/",
about: "/about",
} satisfies Record<string, string>;
const h: "/" = routes.home;
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions g2-satisfies-literal.ts
g2-satisfies-literal.ts(5,7): error TS2322: Type 'string' is not assignable to type '"/"'.
g3 は、g1 から satisfies Record<string, string> を外して as const だけにしたコードです。6 行目に g1 と同じ文が出て、home は "/" でした。
as const satisfies Record<string, string> で、値が数(about: 404)のときは、TS2322 で止まります。
const routes = {
home: "/",
about: 404,
} as const satisfies Record<string, string>;
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions e4-asconst-satisfies-wrong.ts
e4-asconst-satisfies-wrong.ts(3,3): error TS2322: Type 'number' is not assignable to type 'string'.
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja e4-asconst-satisfies-wrong.ts
e4-asconst-satisfies-wrong.ts(3,3): error TS2322: 型 'number' を型 'string' に割り当てることはできません。
satisfies as const の順は TS1355
順番を逆にして、satisfies Record<string, string> as const と書くと、TS1355 で止まります(7.0.2 と 6.0.3 で同じ文)。
const routes = {
home: "/",
about: "/about",
} satisfies Record<string, string> as const;
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions e2-satisfies-asconst.ts
e2-satisfies-asconst.ts(4,3): error TS1355: A 'const' assertion can only be applied to references to enum members, or string, number, boolean, array, or object literals.
--locale ja を付けたときの文です。
$ npx tsc --strict --noEmit --target es2022 --allowImportingTsExtensions --locale ja e2-satisfies-asconst.ts
e2-satisfies-asconst.ts(4,3): error TS1355: 'const' アサーションは、列挙型メンバーへの参照、または文字列、数値、ブール値、配列、オブジェクト リテラルへの参照にのみ適用できます。
よくある質問
satisfies はいつから使えますか?
TypeScript 4.9 から使えます。JSDoc の @satisfies は、TypeScript 5.0 から使えます。
型注釈(: 型)と何が違いますか?
型注釈は変数の型が注釈の型になるので、palette.green が string | RGB になり、toUpperCase() が TS2339 になります。satisfies は式の型を残すので、palette.green は string のままでした。
as はどんな誤りでも通してしまいますか?
通さないものもあります。型どうしが十分に重ならない変換は、TS2352 で止まります(Handbook の説明。d3 と f4 でも止まりました)。一方で、足りないプロパティは、c3 と f1 で通りました。
satisfies で型に合わないと、どんなエラーになりますか?
プロパティの値が違えば TS2322、余分なプロパティは TS2353 です(d1 の bleu)。f3 の colour では、color の候補が付いた TS2561 になりました、足りないプロパティは TS2741 です。文字列や数の値が型に合わないときは TS1360 です。6.0.3 では、足りないプロパティのときに TS1360 の下に TS2741 の文が出ました。
as const satisfies の順番は?
{ … } as const satisfies 型 の順です。逆にして satisfies 型 as const と書くと、TS1355 で止まりました。
まとめ
satisfiesは、式の型が型に合っているかを確かめ、式の型は変えない演算子です(TypeScript 4.9 から)- 型注釈は変数の型が注釈の型になり、
asは型を指定します。palette.green.toUpperCase()は、この 2 つでは TS2339、satisfiesではエラーなしでした - 足りないプロパティは、
satisfiesと型注釈が TS2741 で止まり、asは通りました(試した結果) asでも、型どうしが十分に重ならないときは TS2352 で止まりますas const satisfiesの順に書きます。逆にすると TS1355 です- 7.0.2 と 6.0.3 では、足りないプロパティのときのエラーの番号と、終了コードが違いました
この記事で確かめていないことは、次のとおりです。
- Windows と macOS での動き
- エディタ上での型の見え方
- 7.0 で
satisfiesの扱いが変わったかどうかと、番号が違う理由 - TypeScript 5 系以前での動き
参考資料
- TypeScript 4.9 のリリースノート: The satisfies Operator
- TypeScript 5.0 のリリースノート: satisfies support in JSDoc
- JSDoc Reference: @satisfies
- Handbook: Everyday Types(型注釈)
- Handbook: Everyday Types(型アサーション)
- Handbook: Everyday Types(リテラルの推論と as const)
- Handbook: Object Types(余分なプロパティのチェック)
※この記事は、2026年10月23日時点の公式の資料と照らして確かめています。誤りに気づいたらお問い合わせからお知らせください。


