はじめに
今回はTypeScriptのsatisfiesについて理解を深めたい記事になります。(乱文)
毎回フィーリングで使っていて,ちゃんと理解していないなと思い学習兼備忘録として書いていきます。
satisfiesとは
日本語に訳すと「満たす」という意味になります。
その名の通り、型が指定した条件を満たすかどうかを判定するための関数です。
使い方としては、式 satisfies 型
という形で使います。
typescriptの公式から引用
satisfies演算子を使用すると、式の結果の型を変更せずに、式の型が何らかの型と一致することを検証できます
これはどういうことなのか、具体的な例を見ていきましょう。
type Colors = 'red' | 'green' | 'blue';
type RGB = [red: number, green: number, blue: number];
const palette: Record<Colors, string | RGB> = {
red: [255, 0, 0],
green: '#00ff00',
blue: [0, 0, 255],
};
// 'palette.green' は型 'string | RGB' である可能性があり、
// プロパティ 'toUpperCase' は型 'string | RGB' に存在しません。
const greenNormalized = palette.green.toUpperCase();
このとき、greenNormalizedは以下のような型推論がされてしまい、palette.green
はstring型のはずなのにnumberの可能性があると推論されてしまうためエラーが発生します。
ここでsatisfies
を使って型を指定することでエラーを回避することができます。
type Colors = 'red' | 'green' | 'blue';
type RGB = [red: number, green: number, blue: number];
const palette = {
red: [255, 0, 0],
green: '#00ff00',
blue: [0, 0, 255],
} satisfies Record<Colors, string | RGB>; // <--- satisfiesを使って型を推論
const greenNormalized = palette.green.toUpperCase(); // エラーが発生しない!
palette
をホバーすると以下のように型が推論されていることがわかります。
これが、冒頭の「satisfies演算子を使用すると、式の結果の型を変更せずに、式の型が何らかの型と一致することを検証できます」という意味なんですね。
活用例
satisfiesを使うことで何が嬉しいのかはわかったけど、実際にどういった場面で使うのかがわからなかったのでそこも調べてみました。
1. 型を推論しつつ、保証する
こちらは「typescriptの公式から引用」セクションで紹介した例と同じですが、オブジェクトの型を推論しつつ、型を保証することができます。
const palette = {
red: [255, 0, 0],
green: '#00ff00',
blue: [0, 0, 0],
} satisfies Record<string, string | RGB>;
const palette2: Record<Colors, string | RGB> = {
red: [255, 0, 0],
green: '#00ff00',
blue: [0, 0, 0],
};
こちらはほとんど同じように見えますが、型推論の結果が異なります。
変数をホバーすると以下のように型が表示されます。
const palette: {
red: [number, number, number];
green: string;
blue: [number, number, number];
};
const palette2: Record<Colors, string | RGB>;
これはつまり、palette2.green.toUpperCase()
はエラーが発生してしまいますが、palette.green.toUpperCase()
はエラーが発生しないということです。(palette2のバリューはRGB型である可能性があるため)
2. as const
と併用することで型チェックしつつwideningを防ぐ
wideningとは、型の定義が不必要に広がることを指します。
as const
は、今回の例ではオブジェクトをreadonlyにするために使われています。
const palette = {
red: [255, 0, 0],
green: '#00ff00',
blue: [0, 0, 0],
} as const satisfies Record<string, string | RGB>;
// const palette3: {
// readonly red: [255, 0, 0];
// readonly green: "#00ff00";
// readonly blue: [0, 0, 0];
// }
コメントアウト部がホバーした結果ですが、as const
とsatisfies
を併用することで、型を推論しつつwideningを防ぐことができます。
定数を定義するときには積極的に使っていきたいですね。
また、配列に対しても同様に使うことができます。
const arr = [1, 2, 3];
// const arr: number[]
const arr1 = [1, 2, 3] as const satisfies readonly number[];
// const arr1: readonly [1, 2, 3]
const strArray = ['red', 'green', 'blue'] as const satisfies readonly string[];
// const strArray: readonly ["red", "green", "blue"]
参考:
3. ユニオン型の網羅性チェック
switch文での網羅性チェックを行う際にも使うことができます。
type Colors = "red" | "green" | "blue";
const getHex = (color: Colors) => {
switch (color) {
case 'red':
return '#FF0000';
case 'green':
return '#00FF00';
case 'blue':
return '#0000FF';
default:
return color satisfies never;
}
}
このとき、たとえばblueを削除してしまった場合、default
の部分でエラーが発生します。
ユニオン型が更新され、値が増えたときにもエラーが発生するので変更に強くなります。
まとめ
satifies
は型を推論しつつ、型を保証することができる便利な演算子です。
使用することで、型推論が便利になったりパターンマッチのようなことができたりします。
おわりに
最後までお読みいただきありがとうございました!
今回記事を書いて、なんとなくstiafiesの使い所を理解できた気がします。
参考