Операторы keyof и typeof — мощные инструменты типизации TypeScript. Их совместное использование позволяет строить типы на лету, создавать безопасные функции и выражать структуру объектов максимально гибко.
typeof в TypeScript служит для выведения типа по переменной, а keyof возвращает union всех ключей объекта или типа. В связке они позволяют работать с динамически объявленными объектами и делать взаимосвязанные типы.
Без этих операторов при работе с объектами, enums, и таблицами соответствия часто приходится вручную повторять строки ключей в типах и значениях, что ведёт к ошибкам рассинхронизации и усложняет поддержку кода.
С помощью typeof получают тип из значения переменной, а с помощью keyof строят тип объединения всех её ключей. Итог — автоматизация типизации.
Пример кода:
const ERRORS = { NOT_FOUND: 'Not found', UNAUTHORIZED: 'Unauthorized', SERVER_ERROR: 'Server error', }; // Через typeof получаем тип, а через keyof — все ключи объекта function getErrorMessage(code: keyof typeof ERRORS): string { return ERRORS[code]; }
Ключевые особенности:
Могут ли значения объекта, полученные через typeof, автоматически стать ключами в union-типе?
Нет, typeof возвращает тип структуры объекта, а не значения. Чтобы получить union значений, нужно отдельно получить типы значений.
Что вернёт typeof для enum и что вернет keyof typeof для enum?
Для enum typeof возвращает тип объекта enum (с обоими направлениями: key-value и value-key), а keyof typeof даёт union строковых/числовых ключей этого объекта. Например:
enum Colors { Red = 'R', Blue = 'B' } type ColorKeys = keyof typeof Colors; // 'Red' | 'Blue'
Можно ли с помощью keyof typeof получить type-safe список всех возможных параметров функции, которая принимает ключи объекта?
Да, таким образом вы создаёте функцию, принимающую только допустимые ключи. Это предотвращает ошибки при работе с ключами объектов.
const config = { mode: 'dark', lang: 'ru' }; type ConfigKeys = keyof typeof config; // 'mode' | 'lang' function useConfig(key: ConfigKeys) { // ... }
keyof typeof применим к значениям массива — для массива это индексы, а не значения.typeof работает на уровне типов, а не возвращает runtime-значение.В константе со статусами API вручную прописывают типы строковых ключей:
type StatusCodes = 'OK' | 'FAIL' | 'PENDING'; function isKnownStatus(code: StatusCodes) { /* ... */ }
Плюсы:
Минусы:
Использование keyof typeof для автоматической поддержки списка:
const STATUS = { OK: 1, FAIL: 0, PENDING: 2 }; type StatusKeys = keyof typeof STATUS; function checkStatus(key: StatusKeys) { /* ... */ }
Плюсы:
Минусы: