ts-intl
Chapters:Type Inference & Validation

Type Inference & Validation

ts-intl leverages TypeScript’s type system to check for nonexistent keys, missing parameters, and cross-language dictionary structure inconsistencies.

Key Checking & Autocomplete

Whether using namespaces or dot-separated paths, IDEs support key auto-completion and type checking:

const tCommon = getTranslations("en-US", "common");
tCommon("title"); // Autocomplete: "title" | "greeting" | "items"

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

Dot-path global invocation format:

const tRoot = getTranslations("en-US");
tRoot("common.title"); // Autocomplete: "common.title" | "common.greeting" | ...

Parameter Constraints

When a template contains placeholders, the corresponding parameter object must be passed; when it contains no placeholders, passing extra arguments is forbidden:

const t = getTranslations("en-US", "common");

// No placeholders: parameters are forbidden
t("title");

// Has placeholder: parameters are required
t("greeting", { name: "Alice" });

// @ts-expect-error Missing required parameter { name: string }
t("greeting");

Explicit Parameter Type Annotations

In TypeScript dictionaries, scalar parameter types can be explicitly specified via {name:type} syntax; currently string, number, and Date are supported:

export default {
  status:
    "User {name: string} logged in at {timestamp: Date}. Total: {total: number}",
} as const;

TypeScript validates the parameter types passed by the caller:

const t = getTranslations("en-US");

t("status", {
  name: "Alice",
  timestamp: new Date(),
  total: 42,
});

// @ts-expect-error Type 'string' is not assignable to type 'number'
t("status", { name: "Alice", timestamp: new Date(), total: "42" });

Cross-Language Dictionary Structure Alignment (Schema Alignment)

Taking the language dictionary configured in defaultLanguage as the baseline structure, other languages configured in messages must remain consistent:

  • When keys are missing in other languages, a type error is raised at the initialization configuration.
  • When other languages contain extra keys that do not exist in the baseline language, a type error is raised.
  • Placeholder variable names must remain consistent (e.g., if English is {count}, Chinese and Japanese must also be {count}).
const enUS = {
  welcome: "Welcome, {user: string}!",
} as const;

const zhHans = {
  // @ts-expect-error Missing 'welcome' key
  farewell: "再见",
} as const;

createI18n({
  defaultLanguage: "en-US",
  messages: { "en-US": enUS, "zh-Hans": zhHans },
});

Runtime Dictionary Validation

In development environments (non-production mode), createI18n performs dictionary validation during the initialization phase:

  • Detects whether dictionary keys inadvertently contain dots . (dots are reserved symbols for namespace hierarchies).
  • Emits diagnostic warnings via onError when structural differences are encountered.

This validation is automatically disabled during production builds, incurring no additional runtime overhead.