0Pricing
TypeScript Academy · Урок

Типобезопасность интерполяции

Извлекайте из строк переменные интерполяции и требуйте их указания

«Типобезопасность интерполяции» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 4 уроков всего.

Типобезопасная интерполяция

Сообщения часто содержат заполнители, например "Hello, {name}". Типобезопасная интернационализация извлекает имена этих заполнителей из типа строки сообщения и требует передать соответствующие аргументы.

Цель

Имея литеральный тип сообщения, мы хотим вычислить объект необходимых ему переменных, чтобы вызов t("greet", { name: "Ada" }) был обязательным, а отсутствие name считалось ошибкой компиляции.

Извлечение одного заполнителя

Условный тип на основе шаблонной строки извлекает имя переменной из строки с одним заполнителем. В настоящем коде шаблон записывается обратными кавычками как: строка, открывающая фигурная скобка, выводимая переменная V, закрывающая фигурная скобка, строка. Ниже этот сопоставитель обозначен как BraceMatch.

// Real TS pattern (backtick template literal):
//   matches any text, then {V}, then any text; infers V.

type Var<S extends string> =
  S extends BraceMatch<infer V> ? V : never;

type A = Var<"Hello, {name}">; // "name"

Извлечение нескольких заполнителей

Продолжите рекурсию, чтобы собрать все заполнители в объединение. Шаблон извлекает одну переменную и оставшийся фрагмент, затем рекурсивно обрабатывает этот фрагмент.

// Pattern: any text, {V}, then Rest tail -- infer V and Rest.

type Vars<S extends string> =
  S extends BraceMatchRest<infer V, infer Rest>
    ? V | Vars<Rest>
    : never;

type B = Vars<"Hi {first} {last}!">; // "first" | "last"

От имён к объекту аргументов

Преобразуйте объединение имён в тип обязательного объекта с помощью отображаемого типа.

type ArgsOf<S extends string> = {
  [K in Vars<S>]: string | number;
};

type G = ArgsOf<"Hello, {name}">;
// { name: string | number }

Нет заполнителей — нет аргументов

Если сообщение не содержит заполнителей, Vars имеет значение never, поэтому объект аргументов оказывается пустым. В этом случае параметр аргументов можно сделать необязательным.

type C = Vars<"Goodbye">;       // never
type D = ArgsOf<"Goodbye">;     // {} (empty)

Типизированная функция перевода

Сделайте параметр аргументов зависимым от выбранного ключа, найдя литерал сообщения и вычислив его аргументы.

declare const messages: {
  greet: "Hello, {name}";
  invite: "Join {count} others";
};

declare function t<K extends keyof typeof messages>(
  key: K,
  args: ArgsOf<(typeof messages)[K]>
): string;

Проверка в действии

Теперь компилятор требует указать именно те переменные, которые объявлены каждым сообщением.

t("greet", { name: "Ada" });   // ok
t("greet", {});                 // Error: name is missing
t("invite", { count: 3 });      // ok
t("invite", { name: "x" });     // Error: count missing, name unexpected

Необязательные аргументы для обычных сообщений

Используйте условную перегрузку, чтобы сообщения без заполнителей вообще не требовали второго аргумента.

type MaybeArgs<S extends string> =
  Vars<S> extends never ? [] : [args: ArgsOf<S>];

declare function t2<K extends keyof typeof messages>(
  key: K,
  ...rest: MaybeArgs<(typeof messages)[K]>
): string;

Пользовательские разделители

Если в каталоге используются {{name}} или %{name}, соответствующим образом измените шаблонный строковый шаблон в Vars. Метод остаётся тем же, меняется только окружающий литерал.

Почему это важно

Отсутствующие или указанные с ошибкой переменные интерполяции — классический источник неисправных строк интерфейса ("Hello, undefined"). Извлечение этих переменных на уровне типов превращает такие случаи в ошибки компиляции и документирует контракт каждого сообщения.

Быстрая проверка

Проверьте своё понимание типобезопасности интерполяции.

Итоги

Сопоставляя с образцом литеральные типы сообщений с помощью шаблонных литералов и infer, Вы извлекаете имена заполнителей в объединение типов, сопоставляете их с объектом обязательных аргументов и заставляете функцию перевода требовать именно эти переменные; если их нет, аргументы становятся необязательными.

Часто задаваемые вопросы

Урок «Типобезопасность интерполяции» бесплатный?

Да — полный текст урока «Типобезопасность интерполяции» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 4 уроков всего.

Чему я научусь в уроке «Типобезопасность интерполяции»?

Извлекайте из строк переменные интерполяции и требуйте их указания Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать TypeScript Academy?

Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Типобезопасность интерполяции»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке TypeScript Academy?

Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Типизация ключей переводов
  2. Типобезопасность интерполяции
  3. Множественное число с типами
  4. Вывод типов с учётом локали
← Назад к TypeScript Academy