TypeScript には、文字列そのものを組み立てるのではなく、文字列の「型」を組み立てる仕組みがあります。それが Template Literal Types(テンプレートリテラル型)です。JavaScript のテンプレートリテラル(バッククォートで囲む文字列)とよく似た書き方で、「必ず Hello で始まる文字列だけを受け付ける型」や「top-left や bottom-right のような組み合わせだけを許す型」を定義できます。この記事では、基本の書き方からユニオン型との組み合わせ、組み込みの文字列操作型、そして実務での使いどころまで、初心者〜中級者向けに解説します。TypeScript 4.1 以降で使える機能です。
目次
これは「実行時の文字列」ではなく「型」の機能です
最初に大事な前置きをします。JavaScript のテンプレートリテラル(例: `Hello ${name}`)は、実際に動くプログラムの中で文字列という「値」を作るものです。一方この記事で扱う Template Literal Types は、同じような見た目でも「型」を作る機能で、コンパイル時(型チェックのとき)にしか存在しません。JavaScript に変換された時点で消えてしまうため、実行時には何の影響もありません。「文字列を生成する」のではなく「どんな文字列を受け付けるかを決める」もの、と考えてください。
基本の書き方:バッククォートと ${} で型を組み立てる
テンプレートリテラル型は、バッククォート ` で囲み、その中に ${} で別の型を埋め込んで書きます。次の例では、「Hello のあとに任意の文字列が続く」という形の型を定義しています。
// "Hello " で始まる文字列だけを受け付ける型
type Greeting = `Hello ${string}`;
const a: Greeting = "Hello 太郎"; // OK
const b: Greeting = "Hello world"; // OK
const c: Greeting = "Hi 太郎"; // エラー:"Hello " で始まっていない
${string} の部分は「ここには任意の文字列が入る」という意味です。string のほかに number や boolean なども埋め込めます。たとえば `id-${number}` とすれば、"id-1" や "id-42" のような文字列だけを許す型になります。文字列リテラル型("Hello" のような特定の文字列だけを表す型)を ${} に入れれば、その文字列がそのまま埋め込まれます。
ユニオン型と組み合わせると全パターンに展開される
テンプレートリテラル型の真価は、ユニオン型("a" | "b" のように「どれか」を表す型)と組み合わせたときに現れます。${} にユニオン型を入れると、その全組み合わせが自動的に展開されます。
type Vertical = "top" | "bottom";
type Horizontal = "left" | "right";
// 2 × 2 = 4 通りに展開される
type Position = `${Vertical}-${Horizontal}`;
// 実際の型は次と同じ:
// "top-left" | "top-right" | "bottom-left" | "bottom-right"
const p1: Position = "top-left"; // OK
const p2: Position = "bottom-right"; // OK
const p3: Position = "center"; // エラー:4 通りのどれでもない
Vertical が2通り、Horizontal が2通りなので、掛け合わせて4通りの文字列型が生まれます。複数の ${} にユニオン型を入れると、それぞれの掛け算の数だけパターンが展開されるわけです。手で "top-left" | "top-right" | ... と書き並べる必要がなくなり、要素を追加したときも自動で組み合わせが増えるのが利点です。
組み込みの文字列操作型(Uppercase など)
TypeScript には、文字列リテラル型の大文字・小文字を変換するための組み込みの型が4つ用意されています。これらはテンプレートリテラル型と一緒に使うことが多く、型の中で文字列を加工できます。
| 型 | 説明 |
|---|---|
Uppercase<T> | すべての文字を大文字にする("abc" → "ABC") |
Lowercase<T> | すべての文字を小文字にする("ABC" → "abc") |
Capitalize<T> | 先頭の1文字だけ大文字にする("abc" → "Abc") |
Uncapitalize<T> | 先頭の1文字だけ小文字にする("Abc" → "abc") |
使い方は、対象の文字列型を <> の中に渡すだけです。次の例で挙動を確認してみましょう。
type A = Uppercase<"hello">; // "HELLO"
type B = Lowercase<"HELLO">; // "hello"
type C = Capitalize<"click">; // "Click"
type D = Uncapitalize<"Click">; // "click"
// テンプレートリテラル型の中でも使える
type Shout = `${Uppercase<"warning">}!`; // "WARNING!"
特に Capitalize は、次で紹介するイベント名の生成のように「先頭を大文字にしてつなげる」場面でよく使います。
実務での使いどころ
CSS の px サイズを表す型
「数値のあとに必ず px が付く文字列」を型で表現できます。単位の付け忘れや誤ったフォーマットを、コンパイル時に防げます。
type PxSize = `${number}px`;
const width: PxSize = "16px"; // OK
const gap: PxSize = "8px"; // OK
const bad: PxSize = "16"; // エラー:"px" が付いていない
const bad2: PxSize = "16rem"; // エラー:単位が px ではない
イベント名を on + Capitalize で作る
React のように「click → onClick」というイベントハンドラ名を扱う場面では、Capitalize と組み合わせて型を組み立てられます。元のイベント名の一覧から、対応する on〜 の名前を自動生成できます。
type EventName = "click" | "focus" | "change";
// "on" + 先頭を大文字にしたイベント名
type HandlerName = `on${Capitalize<EventName>}`;
// "onClick" | "onFocus" | "onChange"
const handler: HandlerName = "onClick"; // OK
const wrong: HandlerName = "onclick"; // エラー:C が小文字
API のパスを表す型
API のエンドポイントを「必ず /api/ で始まるパス」として型にしておくと、タイプミスや誤ったパスの指定を防げます。
type ApiPath = `/api/${string}`;
function get(path: ApiPath) {
// 省略:fetch などでパスを使う
}
get("/api/users"); // OK
get("/api/posts/1"); // OK
get("/users"); // エラー:"/api/" で始まっていない
keyof や Mapped Types との組み合わせ
一歩進んだ使い方として、オブジェクトのプロパティ名(keyof で取り出せる)を元に、新しいプロパティ名を持つ型を作ることもできます。Mapped Types(既存の型のプロパティを1つずつ変換して新しい型を作る仕組み)の中でテンプレートリテラル型を使うと、たとえば各プロパティに対応する「getter メソッド名」を自動生成できます。
interface Person {
name: string;
age: number;
}
// 各プロパティに対応する getName / getAge を持つ型を生成
type Getters<T> = {
[K in keyof T & string as `get${Capitalize<K>}`]: () => T[K];
};
type PersonGetters = Getters<Person>;
// {
// getName: () => string;
// getAge: () => number;
// }
[K in keyof T & string as ...] の as の部分でキー名を作り替えているのがポイントです。keyof T だけだと数値や記号のキーも含まれ得るため、& string で文字列のキーに絞ってから Capitalize に渡しています。ここは少し複雑なので、最初は「テンプレートリテラル型はこういう応用にも使える」という程度に押さえておけば十分です。
まとめ
Template Literal Types は、バッククォートと ${} を使って文字列の型を組み立てる機能です。`Hello ${string}` のように形を決めたり、ユニオン型と組み合わせて "top-left" | "top-right" | ... のような全組み合わせを自動展開したりできます。Uppercase / Lowercase / Capitalize / Uncapitalize の4つの組み込み型を使えば、型の中で文字列を大文字・小文字に加工できます。CSS の px サイズ、on${Capitalize<T>} のイベント名、API のパスなど、「決まった形の文字列」を安全に扱いたい場面で活躍します。あくまでコンパイル時の型チェック機能であり、実行時の文字列を作るものではない点だけ、あらためて意識しておきましょう。TypeScript 4.1 以降で使えます。