as const в TypeScript превращает значения и свойства объекта/массива в readonly и литеральные типы. Это даёт строгую типизацию: значения не "расширяются" до базового типа, а сохраняют своё конкретное значение.
Пример:
const a = { status: 'success' }; // Тип: { status: string } const b = { status: 'success' } as const; // Тип: { readonly status: "success" }
Преимущества:
Недостатки/Особенности:
Вопрос: Если использовать as const для массива из строк, какой у него будет тип, и можно ли будет его передать как обычный string[]?
Ответ: Тип будет readonly ["a", "b", "c"], то есть кортеж из литеральных типов с readonly-ограничением. Такой массив несовместим c типом string[]; его нельзя напрямую передать туда, где ожидают изменяемый массив строк.
const arr = ['a', 'b', 'c'] as const; // readonly ["a", "b", "c"] function acceptsStrings(x: string[]) {} acceptsStrings(arr); // Ошибка! Тип несовместим
История
Проект: Хранили список actionTypes как константный массив c as const, затем пытались передавать его в функцию ожидания string[]. Получили ошибку типов, пришлось явно преобразовывать с помощью
.slice()или[...arr].
История
Проект: В Redux-микрофреймворке тип action.type определяли как литерал через as const. При реализации switch-case забыли про строгую типизацию, не обрабатывали все возможные литералы, из-за чего не сработал exhaustive check — ошибка не проявилась, пока не добавили новый экшн.
История
Проект: При авто-генерации API-эндпоинтов описывали их ключи через as const-массив. Попытка использовать эти ключи как индекс обычного Record<string, ...> провалилась из-за рассогласования типов — пришлось добавлять преобразование, либо в явном виде использовать типы ключей из массива.