0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

今回は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の可能性があると推論されてしまうためエラーが発生します。

スクリーンショット 2024-12-23 23.52.53.png

ここで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をホバーすると以下のように型が推論されていることがわかります。

スクリーンショット 2024-12-23 23.56.00.png

これが、冒頭の「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 constsatisfiesを併用することで、型を推論しつつ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の部分でエラーが発生します。

スクリーンショット 2024-12-24 0.40.04.png

ユニオン型が更新され、値が増えたときにもエラーが発生するので変更に強くなります。

まとめ

satifiesは型を推論しつつ、型を保証することができる便利な演算子です。

使用することで、型推論が便利になったりパターンマッチのようなことができたりします。

おわりに

最後までお読みいただきありがとうございました!

今回記事を書いて、なんとなくstiafiesの使い所を理解できた気がします。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?