Константні твердження (as const) у TypeScript
Що таке as const?
as const — це асерція const, яка вказує TypeScript виводити найвужчий можливий тип для значення — роблячи його глибоко readonly з літеральними типами замість розширених типів.
Без vs З as const
typescript
// Без as const — розширені типи
const config = {
url: "https://api.example.com",
port: 3000,
methods: ["GET", "POST"]
};
// тип: { url: string; port: number; methods: string[] }
// З as const — звужено до літералів і readonly
const config = {
url: "https://api.example.com",
port: 3000,
methods: ["GET", "POST"]
} as const;
// тип: {
// readonly url: "https://api.example.com";
// readonly port: 3000;
// readonly methods: readonly ["GET", "POST"];
// }Що робить as const
| Аспект | Без as const | З as const |
|---|---|---|
| Строкові значення | string | Літеральне ("точне значення") |
| Числові значення | number | Літеральне (42) |
| Властивості об'єкта | Змінні | readonly |
| Масиви | Змінний масив | readonly кортеж |
| Вкладені об'єкти | Змінні | Глибоко readonly |
Загальні випадки використання
Створення об'єднань типів з значень
typescript
const ROLES = ["admin", "editor", "viewer"] as const;
type Role = typeof ROLES[number]; // "admin" | "editor" | "viewer"
const STATUS = {
PENDING: "pending",
ACTIVE: "active",
INACTIVE: "inactive",
} as const;
type Status = typeof STATUS[keyof typeof STATUS];
// "pending" | "active" | "inactive"Альтернатива Enum
typescript
// Замість enum:
enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT" }
// Використовуйте as const:
const Direction = {
Up: "UP",
Down: "DOWN",
Left: "LEFT",
Right: "RIGHT",
} as const;
type Direction = typeof Direction[keyof typeof Direction];
// "UP" | "DOWN" | "LEFT" | "RIGHT"Функція з літеральним поверненням
typescript
function getConfig() {
return {
theme: "dark",
lang: "en",
features: ["search", "notifications"],
} as const;
}
const config = getConfig();
config.theme; // "dark" (літерал, не string)
config.features[0]; // "search" (літерал)Дискриміновані об'єднання
typescript
const createAction = <T extends string, P>(type: T, payload: P) =>
({ type, payload } as const);
const increment = createAction("INCREMENT", { amount: 1 });
// { readonly type: "INCREMENT"; readonly payload: { readonly amount: 1 } }Аргументи кортежу
typescript
// Без as const
const args = [1, "hello"]; // (string | number)[]
// З as const
const args = [1, "hello"] as const; // readonly [1, "hello"]
function foo(num: number, str: string) {}
foo(...args); // ✅ Працює, оскільки TypeScript знає точні типиas const vs Object.freeze
| Особливість | as const | Object.freeze |
|---|---|---|
| Коли | Час компіляції | Час виконання |
| Глибина | Глибоке readonly | Поверхневе |
| Літеральні типи | Так | Ні |
| Ефект виконання | Немає | Запобігає модифікації |
typescript
// Для максимальної незмінності: комбінуйте обидва
const config = Object.freeze({
api: "https://api.example.com",
version: 1,
} as const);Важливо:
as const є необхідним для створення типобезпечних констант, альтернатив enum та літеральних об'єднань типів з значень. Це функція, що працює лише під час компіляції, з нульовими витратами під час виконання. Використовуйте її завжди, коли вам потрібно, щоб TypeScript виводив найбільш специфічний можливий тип.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.