ts-intl
チャプター:型推論とバリデーション

型推論とバリデーション

ts-intl は TypeScript の型システムを活用し、存在しないキー、パラメータの欠落、多言語辞書の構造不一致をチェックします。

キーチェックと自動補完

名前空間を使用する場合でもドット区切りパスを使用する場合でも、IDE はキー名の自動補完と型チェックをサポートします:

const tCommon = getTranslations("ja-JP", "common");
tCommon("title"); // 自動補完: "title" | "greeting" | "items"

// @ts-expect-error
tCommon("title_typo");

ドットパスによるグローバル呼び出し形式:

const tRoot = getTranslations("ja-JP");
tRoot("common.title"); // 補完: "common.title" | "common.greeting" | ...

パラメータ制約

テンプレートにプレースホルダーが含まれる場合は対応するパラメータオブジェクトの受け渡しが必須となり、プレースホルダーが含まれない場合は余分な引数の受け渡しが禁止されます:

const t = getTranslations("ja-JP", "common");

// プレースホルダーなし:引数禁止
t("title");

// プレースホルダーあり:引数必須
t("greeting", { name: "田中" });

// @ts-expect-error 必須パラメータ { name: string } が不足しています
t("greeting");

明示的なパラメータ型アノテーション

TypeScript 辞書では、{name:type} 構文によりパラメータのスカラー型を明示的に指定できます。現在 string、number、Date をサポートしています:

export default {
  status:
    "ユーザー {name: string} が {timestamp: Date} にログインしました。合計: {total: number}",
} as const;

TypeScript は呼び出し側が渡したパラメータ型を検証します:

const t = getTranslations("ja-JP");

t("status", {
  name: "田中",
  timestamp: new Date(),
  total: 100,
});

// @ts-expect-error 型 'string' を型 'number' に割り当てることはできません
t("status", { name: "田中", timestamp: new Date(), total: "100" });

多言語辞書の構造整合性(スキーマ整合性)

defaultLanguage で設定された言語辞書を基準構造とし、messages で設定される他の言語はこれと一致している必要があります:

  • 他の言語でキー名が欠落している場合、初期化設定の箇所で型エラーが発生します。
  • 他の言語に基準言語に存在しない余分なキーが含まれている場合、型エラーが発生します。
  • プレースホルダー変数名は全言語で一致している必要があります(例えば英語が {count} の場合、中国語や日本語も {count} である必要があります)。
const jaJP = {
  welcome: "ようこそ、{user: string}さん!",
} as const;

const enUS = {
  // @ts-expect-error 'welcome' キーが不足しています
  farewell: "Goodbye",
} as const;

createI18n({
  defaultLanguage: "ja-JP",
  messages: { "ja-JP": jaJP, "en-US": enUS },
});

ランタイム辞書バリデーション

開発環境(非本番モード)において、createI18n は初期化フェーズで辞書バリデーションを実行します:

  • 辞書キーにドット .(ドットは名前空間の階層予約記号)が誤って含まれていないかを検出します。
  • 構造の差異を検出した際に onError 経由で診断警告を発行します。

本番ビルド時にはこのバリデーションは自動的にオフになり、余分な実行時オーバーヘッドは発生しません。