文字列リテラル型とは何か
文字列リテラル型は、「特定の文字列だけを許可する型」です。
普通の string 型は「どんな文字列でもOK」ですが、文字列リテラル型は「この文字列“だけ”OK」という、もっと狭い世界を表現します。
let s1: string;
s1 = "hello";
s1 = "goodbye"; // どんな文字列でもOK
let s2: "hello";
s2 = "hello"; // OK
// s2 = "goodbye"; // エラー:'"goodbye"' は '"hello"' 型に代入できない
TypeScripts2 の型は string ではなく、"hello" という「値そのもの」を型にしたものです。
これが「文字列リテラル型」の一番シンプルな形です。
文字列リテラル型とユニオン型の組み合わせ
「選択肢が決まっている文字列」を型で表現する
文字列リテラル型が本領発揮するのは、ユニオン型と組み合わせたときです。
たとえば、「状態が "idle" | "loading" | "success" | "error" のどれか」という型を作ってみます。
type Status = "idle" | "loading" | "success" | "error";
let status: Status = "idle";
status = "loading";
status = "success";
// status = "done"; // エラー:'"done"' は 'Status' 型に代入できない
TypeScriptここで Status は、「4つの文字列リテラル型のユニオン」です。"done" のような想定外の文字列を代入しようとすると、コンパイル時に止められます。
この「選択肢を型で固定する」というのが、文字列リテラル型の一番重要な使い道です。
const と文字列リテラル型の関係
const で宣言すると自動的にリテラル型になる
const で文字列を宣言すると、その変数は多くの場合「文字列リテラル型」として扱われます。
const theme = "light";
// theme の型は "light"
let theme2 = "light";
// theme2 の型は string
TypeScriptconst theme は再代入できないので、「この変数は一生 "light" のまま」とコンパイラは判断できます。
その結果、型としても "light" というリテラル型にまで絞り込めます。
一方 let theme2 は、将来 "dark" や "blue" になるかもしれないので、「string 全体」として扱われます。
定数と型をリンクさせるテクニック
この性質を利用して、「定数」と「型」をきれいに結びつけることができます。
const THEME_LIGHT = "light" as const;
const THEME_DARK = "dark" as const;
type Theme = typeof THEME_LIGHT | typeof THEME_DARK;
let t: Theme = THEME_LIGHT;
// t = "blue"; // エラー
TypeScripttypeof THEME_LIGHT は "light" 型、typeof THEME_DARK は "dark" 型です。
それらをユニオンした Theme は、「"light" か "dark" のどちらか」という型になります。
これで、「定数の値」と「型の定義」がズレるリスクを減らせます。
文字列リテラル型が守ってくれるもの
タイプミスや想定外の値をコンパイル時に止める
文字列リテラル型を使うと、「string では広すぎて防げないバグ」をかなり潰せます。
type ApiStatus = "success" | "error";
function handleStatus(status: ApiStatus) {
if (status === "success") {
// ...
} else {
// ...
}
}
handleStatus("success");
// handleStatus("succes"); // エラー(タイプミスをコンパイル時に検出)
TypeScriptもし status の型がただの string だったら、"succes" のようなタイプミスも通ってしまいます。
文字列リテラル型にしておけば、「その文字列は許可されていない」とコンパイル時に教えてくれます。
UI の分岐やモード切り替えとの相性
UI の表示パターンやモード切り替えにも、文字列リテラル型はよく使われます。
type ViewMode = "list" | "grid";
function render(mode: ViewMode) {
if (mode === "list") {
// リスト表示
} else {
// グリッド表示
}
}
render("list");
// render("table"); // エラー
TypeScript「この2パターンしかない」という前提を型に刻んでおくことで、
「第三の謎モード」が紛れ込む余地をなくせます。
初心者がまず身につけたい文字列リテラル型の感覚
難しく考えすぎず、まずはこう捉えてみてください。
「string は“どんな文字列でもOK”」
「文字列リテラル型は“この文字列だけOK”」
「複数の文字列リテラル型を | でつなぐと、“この中のどれかだけOK”という型になる」
そして、実際のコードの中で、
状態(”idle” | “loading” | “success” | “error”)
モード(”list” | “grid”)
テーマ(”light” | “dark”)
のような「限られた選択肢の文字列」が出てきたら、
「これ、string じゃなくて文字列リテラル型にできないかな?」と一度立ち止まってみる。
その一歩を踏み出した瞬間から、あなたのTypeScriptは「ただ動くコード」から「壊れにくいコード」に変わり始めます。
