TypeScriptを使っていると、文字列が入る変数をstring型で済ませてしまう場面が多くあります。
しかし、日付、ID、特定のフォーマットを持つコードなどを扱う際は、文字列にstring型を使うのはあまりに無防備です。
なぜstringだけでは不十分なのか?
例えば、日付を扱う変数を考えてみましょう。
const date: string = '2026-12-34'; // 文法的には正しいが、日付としては不正string型は「どんな文字でも受け入れる」ため、上記のようなあり得ない日付も許容してしまいます。
これが関数の引数やAPIのレスポンス定義に使われていると、実行した際に初めてエラーが発覚し、デバッグに時間を取られることになります。
テンプレートリテラル型による「構造の定義」
TypeScriptには文字列のパターンを型として定義できる「Template Literal Types」という機能があります。
これを利用すると、特定のフォーマットに従わない文字列をコンパイル時点でエラーにできます。
例えば、日付フォーマット(YYYY-MM-DD)を定義した場合は以下のようになります。
// 1桁の数字(0埋めあり)
type OneToNine = '01' | '02' | '03' | '04' | '05' | '06' | '07' | '08' | '09';
// 月(01〜12)
type Month = OneToNine | '10' | '11' | '12';
// 日(01〜31)
// ※厳密には各月の日数までは制御できませんが、基本的な桁と範囲を絞り込めます
type Day = OneToNine | `1${number}` | `2${number}` | `30` | `31`;
// 日付文字列の型(YYYY-MM-DD)
type DateString = `${number}${number}${number}${number}-${Month}-${Day}`;
// 正常なケース
const date: DateString = '2026-04-22';
const invalidMonth: DateString = '2026-13-21';
// Error: Type '"13"' is not assignable to type 'Month'
const invalidFormat: DateString = '2026/04/22';
// Error: 型が一致しない (- ではなく / になっている) テンプレートリテラル型によるメリット
型を定義したコードを読むだけで「この変数はYYYY-MM-DD形式でなければならない」という意図が明確に伝わります。
また、VS Codeなどのエディタであれば、エラーがあれば入力中にリアルタイムで画面上にエラーが表示されるので、すぐに間違えに気づくことができます。
前述の例は日付でしたが、メールアドレスのような特定の型を持つものはテンプレートリテラル型にすることができるので、安全性の観点から、string型のままにしないほうが望ましいです。
// メールアドレスの型
// ※厳密な型ではないが、string型よりは間違えを検出しやすい
type Email = `${string}@${string}.${string}`;
// 正常なケース
const validEmail: Email = "user@example.com";
const invalidEmail: Email = "user@examplecom";
// Error: メールアドレス形式になっていないまとめ
TypeScriptでは「とりあえずstring型」にしてしまいがちですが、それでは値の正しさまでは保証できません。
特に日付やID、特定フォーマットの文字列を扱う場合、string型のままだと不正な値をコンパイル時に検出できず、実行時エラーの原因になります。
テンプレートリテラル型を活用すれば、文字列に構造的な制約を持たせることができ、型の時点で不正な値を防ぐことが可能になります。
これにより、コードの安全性が向上するだけでなく、型から意図が明確に伝わるため、可読性や保守性の向上にもつながります。


