TypeScriptのリテラル型とは?値の制約を型で表現する方法
生徒
「先生、TypeScriptのリテラル型ってよく聞くんですけど、どんなものなんですか?」
先生
「リテラル型は、特定の値そのものを型として扱う仕組みなんです。たとえば、文字列の“OK”や数字の“1”といった値を型として指定できるんですよ。」
生徒
「えっ?“OK”っていう文字そのものが型になるんですか?ちょっと不思議ですね…。」
先生
「そうなんです。少し変わって聞こえるかもしれませんが、これを使うと、変数に許可する値を厳密に制限できるようになります。それでは、実際の例を見ながら詳しく学んでいきましょう!」
1. リテラル型とは?
TypeScriptのリテラル型(Literal Type)とは、「特定の値だけを許可する型」のことです。通常の文字列型(string)や数値型(number)はどんな値でも入れられますが、リテラル型は値を限定します。
たとえば、「変数には“OK”という文字列しか入れてはいけない」というような制約を作れます。これにより、プログラムのバグを防ぎ、より安全で予測可能なコードを書くことができます。
まずは簡単な例を見てみましょう。
let status: "OK" = "OK"; // OKという文字列だけが許可される
// status = "NG"; // エラー!"NG"は許可されていない
この例では、変数statusには“OK”という文字列しか代入できません。もし“NG”など別の文字列を代入しようとすると、TypeScriptが「型が違う」とエラーを出してくれます。
2. リテラル型の種類
リテラル型にはいくつかの種類があります。代表的なものは次の3つです。
- 文字列リテラル型(例:「"yes"」「"no"」など)
- 数値リテラル型(例:1、2、3 など)
- 真偽値リテラル型(例:
trueまたはfalse)
それぞれの例を見てみましょう。
// 文字列リテラル型
let answer: "yes" | "no";
answer = "yes"; // OK
// answer = "maybe"; // エラー!
// 数値リテラル型
let level: 1 | 2 | 3;
level = 2; // OK
// level = 4; // エラー!
// 真偽値リテラル型
let isReady: true;
isReady = true; // OK
// isReady = false; // エラー!
このように、リテラル型を使うと、変数に入る値をピンポイントで指定することができます。これは「間違った値を代入しないようにする」強力な仕組みです。
3. リテラル型とユニオン型の組み合わせ
リテラル型は、ユニオン型(複数の型を「または」でつなげる型)と一緒に使うことで、さらに便利になります。
たとえば、「“OK”または“NG”だけを許可する」ように制約することが可能です。
let result: "OK" | "NG";
result = "OK"; // OK
result = "NG"; // OK
// result = "PENDING"; // エラー!
このように書くことで、変数resultには“OK”と“NG”以外の文字列を入れられなくなります。つまり、プログラムのミスを防げるわけです。
4. 関数にリテラル型を使う
リテラル型は、関数の引数にも使えます。これにより、「関数が受け取れる値を限定する」ことができます。
function printStatus(status: "start" | "stop") {
console.log("現在の状態:", status);
}
printStatus("start"); // OK
// printStatus("pause"); // エラー!
このようにすれば、関数に間違った文字列を渡す心配がなくなります。開発が進んでプログラムが複雑になっても、TypeScriptがしっかり守ってくれるんです。
5. オブジェクトにリテラル型を使う
リテラル型は、オブジェクトのプロパティにも指定できます。これにより、「特定の状態を持つ設定オブジェクト」などを安全に扱うことができます。
type Config = {
mode: "dark" | "light";
version: 1 | 2;
};
let userConfig: Config = {
mode: "dark",
version: 2
};
// userConfig.mode = "blue"; // エラー!
このように、あらかじめ決まった選択肢しか設定できないようにすることで、意図しない設定ミスを防ぐことができます。
6. constとリテラル型の関係
TypeScriptでは、constを使うと自動的にリテラル型が推論されることがあります。つまり、定数に代入した値そのものが型として扱われるのです。
const color = "red";
// colorの型は "red"(stringではなくリテラル型)
一方、letで宣言すると、型は一般的なstringになります。つまり、リテラル型として扱いたいときは、constを使うと良いでしょう。
7. リテラル型を使うメリット
リテラル型を使うと、次のようなメリットがあります。
- 誤った値の代入を防げる
- コードの意図が明確になる
- 開発中にエラーを早期に検出できる
特に、大規模なシステム開発やチーム開発では、リテラル型が非常に役立ちます。「この変数にはこれ以外の値を入れてはいけない」というルールを型で表現できるからです。
まとめ
TypeScriptのリテラル型について学んできました。リテラル型とは、文字列や数値、真偽値など特定の値だけを許可する型のことです。これにより、変数に入る値を厳密に制限でき、プログラムのバグを未然に防ぐことができます。文字列リテラル型、数値リテラル型、真偽値リテラル型などを使い分けることで、コードの安全性と可読性を高められます。
さらに、ユニオン型と組み合わせることで複数の許可値を扱えるようになり、関数の引数やオブジェクトのプロパティにも適用することが可能です。これにより、プログラムの意図が明確になり、誤った値の代入を防ぐ効果が得られます。また、constを活用すると自動的にリテラル型が推論されるため、より安全に定数値を管理することができます。
リテラル型の具体例
// 文字列リテラル型とユニオン型の組み合わせ
let result: "OK" | "NG";
result = "OK"; // OK
result = "NG"; // OK
// result = "PENDING"; // エラー!
// 関数の引数にリテラル型を使用
function setMode(mode: "dark" | "light") {
console.log("設定モード:", mode);
}
setMode("dark"); // OK
// setMode("blue"); // エラー!
// オブジェクトプロパティにリテラル型を使用
type Config = {
version: 1 | 2;
theme: "dark" | "light";
};
let userConfig: Config = {
version: 1,
theme: "light"
};
// userConfig.theme = "blue"; // エラー!
このように、リテラル型を適切に使うと、プログラムの安全性を高め、意図しない値の代入を防げます。特に初心者でも、変数や関数、オブジェクトの値を制限することで、コードの理解が深まり、保守性も向上します。
生徒
「リテラル型を使うと、変数にどんな値が入るかを事前に決められるんですね。これなら間違った値を代入してしまう心配が減ります。」
先生
「そうです。特に文字列や数値の選択肢を制限したいときに便利ですし、関数やオブジェクトに使えば、プログラム全体の安全性が高まります。」
生徒
「ユニオン型と組み合わせれば、複数の値も許可できるんですね。これで条件分岐や設定値も安心して扱えます。」
先生
「その通りです。TypeScriptの型システムを活用して、バグを減らしながら読みやすいコードを書くことが大切です。学んだことを意識して、自分のプロジェクトでもリテラル型を試してみてください。」