【入門編】 テンプレートリテラル型によるキーのリマッピング – TypeScript実践ガイド

TypeScriptの世界へようこそ!チーフアーキテクトの私です。

日々のフロントエンド開発、本当にお疲れ様です。「型定義ってなんだか堅苦しいし、エラーばかり出てイライラする……」なんて、最初のうちは誰もが通る道です。大丈夫ですよ、今日お話しする内容を知れば、きっとTypeScriptを書くのが少し楽しくなりますから。

さて、今回はTypeScriptの中級者へのステップアップとして避けて通れない、だけど名前からして難しそうな「テンプレートリテラル型によるキーのリマッピング」というテーマを取り上げます。

「待って待って、横文字が多すぎて頭がパンクしそう!」という声が聞こえてきそうですね。安心してください。今回は難しい専門用語はちょっと横に置いて、身近な「お買い物の流れ」や「リモコンのボタン」に例えながら、一緒にゆっくり紐解いていきましょう。

—

1. まずはイメージから!「キーのリマッピング」ってなに?

いきなりコードを書く前に、頭の中でイメージを膨らませてみましょう。

例えば、あなたがカフェのオーナーだとします。メニュー表には「コーヒー」「ケーキ」という商品名(=オブジェクトの「キー」)が書いてありますよね。
これを、お客さん向けではなく、「裏方の店員さんが注文を受け取るための専用伝票」に自動で変換したいとします。

  • 「コーヒー」というキー ➔ 「getコーヒー」に変えたい!
  • 「ケーキ」というキー ➔ 「getケーキ」に変えたい!

このように、「すでにあるオブジェクトのキーの名前を、ルールを決めてパパッと別の名前に組み替える(リマッピングする)」こと。これが、今回やりたいことの正体です。

TypeScriptの「Mapped Types(マップ型)」という機能を使うと、この面倒な名前の書き換えを、コンピュータにぜーんぶお任せできちゃうんです。手作業で1つずつ書く必要はもうありません。

—

2. テンプレートリテラル型ってなに?

次に、「テンプレートリテラル型」という言葉の味付けです。

JavaScriptには、“ `こんにちは、${name}さん!` “ のように、バッククォートを使って文字列の中に変数を埋め込む便利な機能(テンプレートリテラル)がありますよね。
あれの「型バージョン」が、テンプレートリテラル型です。

例えば、こんな風に使います。

type Action = ‘Read’ | ‘Write’;

// ‘Read’ なら ‘doRead’ に、’Write’ なら ‘doWrite’ に自動でなる!
type ActionName = `do${Action}`;
// 結果は ‘doRead’ | ‘doWrite’ という新しい型になります

文字と文字をガチャンコして、新しい型の世界を作り出す。これがテンプレートリテラル型です。

—

3. 実践!getter/setterを自動生成してみよう

お待たせしました。いよいよ今回の本丸である「キーのリマッピング」を使って、「オブジェクトのプロパティから、自動的にgetter(値を取り出す関数名)の型を作る」コードを見てみましょう。

エディタを開く心の準備はいいですか? コピペして動かせるコードを用意しました。

/

  • ユーザーの情報を表すベースの型
  • 「名前」と「年齢」を持っています

/
type User = {
name: string;
age: number;
};

/

  • 【ここが今回の魔法の部分!】
  • 渡されたオブジェクトのキーを変換して、getterの型を自動で作ります

/
type MakeGetters = {
// ① [K in keyof T] で、元のオブジェクトのキー(name, age)を1つずつ取り出す
// ② as `get${Capitalize}` で、キーの先頭に “get” をくっつけてリマッピング(名前変更)する
// ③ 元のプロパティの中身(string や number)をそのまま値の型として持たせる
[K in keyof T as `get${Capitalize}`]: () => T[K];
};

// さあ、魔法を使ってみましょう!
type UserGetters = MakeGetters;

/

  • 出来上がった UserGetters の中身は、実質的に以下のようになっています:
  • {
  • getName: () => string;
  • getAge: () => number;
  • }

/

// 動作確認用のオブジェクトを作ってみます
const myUserGetters: UserGetters = {
getName: () => “TypeScript太郎”,
getAge: () => 25,
};

console.log(myUserGetters.getName()); // “TypeScript太郎” が出力されます!

どうでしょう? `MakeGetters` という型を通すだけで、`name` が `getName` に、`age` が `getAge` に華麗に変身しましたよね。

※コードの中に出てきた `Capitalize` というのは、「最初の文字を大文字にする」というTypeScriptの優しいおせっかい機能(組み込み型)です。`name` を `Name` にして、`getName` が綺麗に作れるようにこっそり手助けしてくれています。

—

4. 現場でつまずきやすいポイントと「大丈夫だよ」のフォロー

この「キーのリマッピング(`as` を使った書き換え)」、最初は私も「なんだこの記法は……!」と頭を抱えました。ここでよくみんなが引っかかるポイントをこっそりシェアしますね。

1. `as` の後ろの書き方が難しく見える問題

  • 大丈夫です。呪文のように覚える必要はありません。「元のキー(`K`)を、こういう文字列の形に改造して新しいキー名にするよ!」という指定をしているだけです。

2. 「そんな複雑な型、いつ使うの?」という疑問

  • 正直に言います。日常の小さなWeb制作で毎日書くようなものではありません。でも、大規模なライブラリを作るときや、APIのデータをきれいな形に自動変換したいとき、このテクニックを知っていると「神……!」と自分で自分のコードを褒めたくなる瞬間が必ず来ます。

最初は仕組みが完璧に分からなくても、「型って、こんなに柔軟に名前を組み替えることができるんだ!」というワクワク感だけ持ち帰ってもらえれば大成功です。

—

まとめ

今回は、テンプレートリテラル型とMapped Typesを組み合わせた「キーのリマッピング」についてお話しました。

  • キーのリマッピングを使えば、オブジェクトのキー名を自由自在に変換できる。
  • テンプレートリテラル型を組み合わせることで、`get` や `set` などのプレフィックス(接頭辞)を自動付与できる。
  • 最初は難しく見えるけど、一つひとつ分解して読めば、TypeScriptはあなたの最高の味方になってくれる!

フロントエンドの開発は、ときに泥臭く、予期せぬエラーとの格闘の連続です。でも、こうした型システムの奥深さを少しずつ知っていくと、コードを書く手が止まらなくなるような面白さを感じられるはずです。

あなたのTypeScriptライフが、今日からもう少しだけ楽しく、快適になりますように。
それでは、また次のコードレビューでお会いしましょう!チーフアーキテクトでした。

コメント

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