【入門編】 satisfies演算子による型チェック – TypeScript実践ガイド

TypeScriptでの型定義、毎日本当にお疲れ様です!
「あれ? 型を厳しくすると、さっきまで使えていた便利なメソッドが消えちゃった……」「かといって `any` に逃げると、型安全の安心感がなくなって不安……」

そんな、TypeScriptの「あるあるな悩み」に直面して、そっとエディタを閉じそうになったことはありませんか? 大丈夫です、そのモヤモヤを感じるということは、あなたが型安全のありがたさと、現実のコードの柔軟さのバランスに真剣に向き合っている証拠です。

今日は、そんなあなたの救世主となってくれる、ちょっと新しくてめちゃくちゃ頼れる機能`satisfies`(サティスファイーズ)演算子について、おしゃべりするような感覚でゆっくり紐解いていきましょう。

—

1. まずは身近な例えから:「おめかし」と「普段着」のジレンマ

想像してみてください。あなたは今、ちょっとおしゃれなレストランに行くために、クローゼットから服を選んでいます。

ここで、コーディネートのルール(型)を一つ決めました。

  • ルール:靴の色は、トップスかボトムスのどちらかと「お揃い(同系色)」でなければならない!

あなたは手持ちの服から、次のような組み合わせを選びました。

  • トップス:白
  • ボトムス:黒
  • 靴:白

これをTypeScriptの世界で表現してみましょう。

// 服の色のルール(型定義)
type Color = “白” | “黒” | “赤” | “青”;

type Outfit = {
top: Color;
bottom: Color;
shoes: Color;
};

ここで、従来のTypeScriptのやり方(型注釈)でコーディネートを固定してみます。

// 従来の方法(型注釈 : Outfit をつける)
const myOutfit: Outfit = {
top: “白”,
bottom: “黒”,
shoes: “白”, // トップスとお揃いだからOK!
};

めでたしめでたし……と言いたいところですが、ここでちょっとした悲劇が起きます。
あなたは後から、「今日着たトップスの色(`top`)の文字数を、コード上でちょっと調べたいな」と思いました。文字列なので `.length` や `toUpperCase()` などの文字列メソッドを使いたくなりますよね。

そこで `myOutfit.top.toUpperCase()` と書いてみると……あれ?
TypeScriptが冷たくこう言ってきます。
> 「エラー:`top` はただの `”白” | “黒” | “赤” | “青”` という広い型だから、そんな文字列専用のメソッドは使えないよ!」

……えっ? さっき「白」って書いたのに? 確かに私は「白」って代入したのに、TypeScriptくんはそれを忘れて、ただの「Color型の一種」としてしか見てくれないのです。これが、従来の型定義でみんなが一度はつまずく「もどかしさ」でした。

—

2. そこで登場するのが `satisfies` 演算子です!

「ルール(型)にはちゃんと適合(satisfy)させたい! でも、私が書いた具体的な中身の形(推論された型)も、そのまま記憶しておいてほしい!」

そんなわがままを完璧に叶えてくれるのが、TypeScript 4.9から導入された`satisfies`演算子です。

先ほどのコードを、`satisfies` を使って書き換えてみましょう。

type Color = “白” | “黒” | “赤” | “青”;

type Outfit = {
top: Color;
bottom: Color;
shoes: Color;
};

// satisfies を使った書き方
const myOutfit = {
top: “白”,
bottom: “黒”,
shoes: “白”,
} satisfies Outfit; // ここに注目!

これだけで、世界がガラリと変わります。何が起きるかというと……?

1. ルールのチェックはしっかり行われる
もしうっかり `shoes: “黄色”` なんて書いてしまえば、「おいおい、`Color` 型に黄色なんてないよ!」と、TypeScriptがちゃんと怒ってくれます。
2. でも、具体的な中身の型(リテラル型)は保持される!
TypeScriptは、「あ、この人は `top` に `”白”` って書いたんだな」という具体的な情報を忘れません。

そのため、こう書くことができるようになります!

// 「白」という具体的な文字列として認識されているので、文字列のメソッドが使える!
const topLength = myOutfit.top.length; // 1 (文字)
const upperTop = myOutfit.top.toUpperCase(); // エラーにならない!

「ちゃんとルールを守っているかチェックしてほしい。だけど、私が書いた細かい情報まで、キョロキョロ見渡して覚えておいてほしい!」
そんな願いをスマートに叶えてくれる、それが `satisfies` の優しさなんです。

—

3. Web制作・開発の現場でよくある実務パターン

「理屈は分かったけど、実際のWeb制作やアプリ開発の現場では、どんな時に使うの?」
そんな疑問に答えるために、本当によくある実務のシチュエーションを見てみましょう。

シチュエーション:テーマカラー設定オブジェクトの管理

Webサイトやアプリを作るとき、ボタンの色や背景色をまとめた「テーマ設定オブジェクト」を作ることはよくありますよね。

// 許容するカラーコードの型
type RGB = `rgb(${number}, ${number}, ${number})`;
type ThemeColor = string | RGB;

// サイト全体のテーマ設定
type Theme = {
primary: ThemeColor;
secondary: ThemeColor;
accent: ThemeColor;
};

ここで、実際のテーマ設定を作るファイルを書いてみます。

const siteTheme = {
primary: “rgb(255, 100, 0)”, // メインカラー
secondary: “#333333”, // サブカラーは16進数で!
accent: “blue”, // アクセントカラー
} satisfies Theme;

もしここで `satisfies Theme` を使わずに、普通の型注釈(`: Theme`)をつけてしまうとどうなるでしょうか?
TypeScriptは `siteTheme.primary` などの型をすべて、親である `ThemeColor`(つまりただの `string`)として丸めてしまいます。

その結果、後から「あ、`primary` の正確な値を使って、CSSの変数を自動生成したいな」と思ったときに、それがどんな形式の文字列だったのか、TypeScriptが分からなくなってしまうのです。

しかし、`satisfies Theme` を使っていれば、TypeScriptはこう覚えていてくれます。

  • `siteTheme.primary` はただの `string` じゃなくて、 `”rgb(255, 100, 0)”` という具体的な値なんだな!
  • `secondary` は `”#333333″` なんだな!

このおかげで、オブジェクトの型安全(スペルミスやルールの逸脱を防ぐ)を完全に担保しながら、その中身をより高度に、ピンポイントでコードに利用できるようになるのです。これは大規模なフロントエンド開発において、本当に強力な武器になります。

—

まとめ:怖がらなくて大丈夫、少しずつ味方にしていこう

いかがでしたでしょうか?
`satisfies` 演算子は、一見するとちょっと難しそうな名前をしていますが、要するに「お行儀よくルールチェックを受けつつ、自分が書いた個性を失わない魔法の言葉」です。

  • 「型を厳しくすると、便利なプロパティやメソッドが消えて困る……」
  • 「かといって型を緩くしてバグの温床にするのは嫌だ……」

そんなジレンマにぶつかったときは、思い出したように `satisfies` をそっとコードに添えてみてください。「あ、これこれ、こういうのが欲しかったんだよ!」ときっと感動してもらえるはずです。

TypeScriptの型システムは、私たち開発者を縛り付けるための冷たい檻ではなく、最高のコードを書くための心強い相棒です。焦らず、一歩一歩、こういった便利な機能を味方にしながら、一緒に楽しくコードを書いていきましょう!

コメント

タイトルとURLをコピーしました