【入門編】 Template Literal Types (テンプレートリテラル型) – TypeScript実践ガイド

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

日々のフロントエンド開発、本当にお疲れ様です。「型定義ってなんだか堅苦しくて難しそう…」「`any`でとりあえず逃げちゃえ!」そんな風に心が折れそうになっていませんか? 大丈夫ですよ、最初はみんなそこを通ります。私も昔はエラー画面と睨めっこしながらコーヒーを何杯も飲み干していました。

今回は、そんなTypeScriptの数ある機能の中でも、知ると思わず「おっ!」と感動してしまう、ちょっとおしゃれで実用的な機能「Template Literal Types(テンプレートリテラル型)」についてお話しします。

難解な専門用語はなるべく置いておいて、身近な「お買い物」のイメージから優しく紐解いていきましょう!

—

そもそも「テンプレートリテラル型」ってなに?

JavaScriptやTypeScriptを書くとき、バッククォート(“ ` “)を使って変数を文字列に埋め込んだ経験はありませんか? 例えばこんなやつです。

const fruit = “りんご”;
console.log(`今日のデザートは${fruit}です!`); // 「今日のデザートはりんごです!」と出力される

あれの「型バージョン」が、テンプレートリテラル型です。

要するに、「いくつかの決まった文字列のパーツをパズルのように組み合わせて、新しい文字列のルール(型)を作っちゃおうぜ!」という機能なんです。

身近な例えでお話します

想像してみてください。あなたはカフェのアプリを作っています。
メニューには「サイズ(S, M, L)」と「ドリンクの種類(coffee, tea)」がありますよね。

これらを組み合わせると、注文のコード(ID)はこんな風になりそうじゃないですか?

  • `s-coffee`
  • `m-coffee`
  • `l-coffee`
  • `s-tea`
  • `m-tea`
  • `l-tea`

これを全部手書きで型定義しようとすると……想像しただけで指がつりそうですよね。「あ、Mのコーヒーを `M-coffee` って大文字にしちゃった!エラーにならない!」なんてヒューマンエラーも起き放題です。

そんなときこそ、テンプレートリテラル型の出番です!

—

実際にコードを書いてみよう

百聞は一見にしかず。まずはエディタを開いたつもりで、以下のコードを見てみてください。

// カフェのサイズとドリンクのパーツを定義します
type CupSize = “s” | “m” | “l”;
type DrinkType = “coffee” | “tea”;

// ここがテンプレートリテラル型!
// カップサイズとドリンクの種類をハイフンつなぎで合体させます
type MenuId = `${CupSize}-${DrinkType}`;

// さて、MenuIdの中身はどうなっているでしょうか?
// 実際には以下の6つの文字列リテラル型が自動で生成されます!
// “s-coffee” | “s-tea” | “m-coffee” | “m-tea” | “l-coffee” | “l-tea”

すごいでしょう? パーツを定義して合体させるだけで、TypeScriptが勝手に全パターンの組み合わせを作ってくれるんです。

では、実際にこの型を関数で使ってみましょう。

// 注文を受け付ける関数を作ります
function orderDrink(id: MenuId) {
console.log(`${id} のご注文ですね。承りました!`);
}

// 【成功する例】
orderDrink(“s-coffee”); // バッチリ動きます!
orderDrink(“l-tea”); // こちらもOK!

// 【つまずきポイント:間違った値を渡してみる】
// orderDrink(“xl-coffee”);
// ❌ ここでTypeScriptが赤く波線を出して怒ってくれます!
// 「そんなメニューないよ! “s-coffee” | “s-tea” | … のどれかにして!」と教えてくれます。

どうですか? 「うっかりミス」をコードを書いている最中に、TypeScriptの先生が優しくガードしてくれる安心感。これがテンプレートリテラル型の最大の魅力です。

—

実務で役立つ!ちょっと便利な応用テクニック

基本がわかったところで、実際のWeb制作やアプリ開発で「おっ、これ使えるな」という実用的なパターンを一つご紹介します。

例えば、CSSのクラス名や、コンポーネントの「色(バリアント)」と「サイズ」を管理する場面です。

type ButtonColor = “primary” | “secondary” | “danger”;
type ButtonSize = “sm” | “lg”;

// 「color-size」という命名規則のクラス名を自動生成する型
type ButtonClassName = `btn-${ButtonColor}-${ButtonSize}`;

// 生成される型:
// “btn-primary-sm” | “btn-primary-lg” |
// “btn-secondary-sm” | “btn-secondary-lg” |
// “btn-danger-sm” | “btn-danger-lg”

const myButtonClass: ButtonClassName = “btn-primary-lg”; // OK!
// const badButtonClass: ButtonClassName = “btn-blue-sm”; // ❌ “blue”なんて色はないよ!と怒られる

このように、チームで開発するときに「命名規則のブレ」を型レベルでガチッと防ぐことができるのです。バックエンドから返ってくるAPIのレスポンス形式や、イベント名(`on-click`, `on-change` など)の定義にもめちゃくちゃ重宝しますよ。

—

まとめ:恐れずに、まずはパズル感覚で楽しもう

今回はテンプレートリテラル型の基本と、その心地よさを紹介しました。

  • 文字列のパーツ(Union型)を “ `${…}` “ で囲んで合体できる!
  • 組み合わせの全パターンをTypeScriptが自動で作ってくれる!
  • うっかりミスを未然に防げるから、コードに自信が持てるようになる!

最初はこの記法を見たときに「なんだか難しそうだな…」と感じたかもしれませんが、やっていることは文字通りの「パズル」や「掛け算」です。

つまずいたときは、「あ、TypeScriptの先生が手伝ってくれてるんだな」と気楽に捉えて、まずは小さな文字列から組み合わせて遊んでみてください。あなたのフロントエンドライフが、少しでも快適で楽しいものになりますように。

それでは、また次の現場でお会いしましょう!チーフアーキテクトでした。

コメント

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