Типизация ключей переводов
Выводите объединение допустимых ключей из файлов сообщений
«Типизация ключей переводов» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 4 уроков всего.
Выведение типизированных ключей переводов
В типобезопасной настройке i18n набор допустимых ключей переводов выводится из объекта сообщений. Опечатка вроде t("greetng") становится ошибкой компиляции, а не ошибкой отсутствующей строки во время выполнения.
Объект сообщений
Начните с обычного объекта сообщений. Он является единственным источником истины и для значений, и для типа ключей.
const messages = {
greeting: "Hello",
farewell: "Goodbye",
cart: {
empty: "Your cart is empty",
checkout: "Proceed to checkout",
},
} as const;Ключи верхнего уровня с оператором получения ключей
Для плоского объекта конструкция keyof typeof выдаёт объединение его ключей.
type TopKeys = keyof typeof messages;
// "greeting" | "farewell" | "cart"Проблема вложенности
Каталоги реальных сообщений имеют вложенную структуру. Нам нужны пути с точками, такие как "cart.empty", а не только ключи верхнего уровня. Нужен рекурсивный тип, который обходит объект.
Рекурсивный тип пути
Условный и отображаемый тип строят пути с точками, рекурсивно проходя по вложенным объектам и добавляя ключи в качестве префиксов. Префикс использует шаблонный строковый тип, записываемый в настоящем коде с обратными кавычками как [backtick]${K}.${Paths<T[K]>}[backtick]. Ниже мы показываем его как JoinPath(K, дочерний элемент), чтобы сохранить читаемость списка.
type JoinPath<K extends string, Rest extends string> = K + "." + Rest;
// (Real TS uses a template literal type:
// the K dot Rest pattern delimited by backticks.)
type Paths<T> = {
[K in keyof T & string]: T[K] extends string
? K
: K | (T[K] extends object
? JoinPath<K, Paths<T[K]>>
: never);
}[keyof T & string];Применение типа
Передача типа сообщений в Paths даёт все допустимые пути с точками.
type MsgKey = Paths<typeof messages>;
// "greeting" | "farewell" | "cart" | "cart.empty" | "cart.checkout"Только конечные ключи
Часто нужны только конечные пути — фактические строки, исключая промежуточные объекты. Измените рекурсию так, чтобы пропускать узлы, не являющиеся строками. Префикс «K-точка-дочерний элемент» снова использует шаблонный строковый тип (в настоящем коде он ограничен обратными кавычками), здесь показанный как JoinPath.
type LeafPaths<T> = T extends string
? ""
: {
[K in keyof T & string]: T[K] extends string
? K
: JoinPath<K, LeafPaths<T[K]>>;
}[keyof T & string];
// "greeting" | "farewell" | "cart.empty" | "cart.checkout"Типизированная функция перевода
Ограничьте параметр функции перевода выведенным объединением ключей, чтобы компилировались только допустимые ключи.
declare function t(key: LeafPaths<typeof messages>): string;
t("cart.empty"); // ok
t("cart.missing"); // Error: not a valid keyОпределение типа значения
Можно пойти дальше и вывести тип значения по пути — это полезно, когда сообщения содержат элементы нестрокового типа. Условный тип с индексацией по пути проходит по точкам. Он разделяет путь с помощью шаблона шаблонного строкового типа, который в настоящем коде записывается обратными кавычками в форме «начало, точка, остаток» с выводом типов. Ниже это разделение обозначено как SplitHead/SplitRest.
// Conceptually: split "cart.empty" into Head="cart", Rest="empty"
// using a template literal pattern with infer.
type ValueAt<T, P extends string> =
P extends SplitHead<infer Head, infer Rest>
? Head extends keyof T ? ValueAt<T[Head], Rest> : never
: P extends keyof T ? T[P] : never;Почему важно объявление константой
Без as const строковые значения расширяются до string, и Вы теряете сведения о литералах, необходимые позднее (например, для извлечения заполнителей). Всегда объявляйте каталоги как константы.
Почему это важно
Выведение ключей из каталога означает, что добавление, переименование или удаление сообщения мгновенно обновляет допустимый тип ключа повсюду. Не нужно поддерживать центральное перечисление или устаревшие строковые константы.
Быстрая проверка
Проверьте своё понимание типизации ключей переводов.
Итоги
Вы вывели объединение допустимых ключей из объекта messages, используя keyof и рекурсивный тип пути на основе шаблонных строк. Варианты только с конечными узлами исключают промежуточные объекты, типизированная функция t отклоняет недопустимые ключи, а as const сохраняет сведения о литералах, необходимые средствам работы с типами.
Часто задаваемые вопросы
Урок «Типизация ключей переводов» бесплатный?
Да — полный текст урока «Типизация ключей переводов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Типизация ключей переводов»?
Выводите объединение допустимых ключей из файлов сообщений Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать TypeScript Academy?
Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Типизация ключей переводов»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке TypeScript Academy?
Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Типизация ключей переводов
- Типобезопасность интерполяции
- Множественное число с типами
- Вывод типов с учётом локали