As const в Typescript
- понедельник, 8 января 2024 г. в 00:02:30
Привет, Хабр!
В разработке часто возникают ситуации, когда точность типов и нежелание допускать неясности в коде становятся первостепенными задачами. В таких случаях, разработчикам приходится искать инструменты, предоставляющие максимальную ясность и строгость в определении данных. Один из таких инструментов — ключевое слово as const
. В данной статье мы рассмотрим, как as const
может повысить уровень строгости и предсказуемости, а также рассмотрим практические примеры его использования для создания неизменяемых и точных типов.
Когда вы используете as const
для переменной или значения, TypeScript уточняет тип этой переменной до ее точного значения или комбинации литеральных типов. Это часто используется для создания неизменяемых значений и гарантирования того, что TypeScript будет рассматривать значения как конкретные литералы, а не расширять типы.
Пример:
Представьте, что нам нужно написать функцию для открытия входной двери в дом. Пишем функцию, которая принимает параметром ключ, и проводит с ним какие-либо операции.
const wallet = {
key: "open_door_pls"
}
const openDoor = (key: "open_door_pls") => {
//...
}
Но, когда мы пытаемся использовать функцию openDoor
с ключом из нашего бумажника, почему-то происходит следующее:
const wallet = {
key: "open_door_pls"
}
const openDoor = (key: "open_door_pls") => {
//...
}
openDoor(wallet.key) // ERROR: Argument of type 'string' is not assignable to parameter of type '"open_door_pls"'
Почему же мы попали в такую ситуацию?
Всё дело в том, что wallet.key
у нас никак не привязан к значению "open_door_pls”
, и по сути является просто элементом с типом string
, значение которого можно легко изменить на любое другое:
const wallet = {
key: "open_door_pls"
}
wallet.key = "cucumber" // код отрабатывает без ошибок
Чтобы избежать такого поведения, и сделать все элементы wallet полноценными, неизменяемыми (readonly
) значениями, мы можем воспользоваться конструкцией as const
:
const wallet = {
key: "open_door_pls"
} as const
wallet.key = "cucumber" // ERROR: Cannot assign to 'key' because it is a read-only property.
Элементы wallet
привязались к своим значениям и теперь имеют флаг readonly
.
Что в конечном итоге решило нашу проблему с параметром функции openDoor
:
const wallet = {
key: "open_door_pls"
} as const;
const openDoor = (key: "open_door_pls") => {
//...
};
openDoor(wallet.key) // код отрабатывает без ошибок
Проблема Object.freeze()
заключается в том, что после заморозки объекта, readonly
присваевается только элементам на верхнем уровне вложенности.
const car = Object.freeze({
name: "Porshe Cayenne",
equipment:{
engine: "MDC.AB"
}
});
car.equipment.engine = "F8CV"; // без проблем изменили двигатель
При использовании as const
компилятор на любом уровне вложенности укажет, что программист пытается изменить константу.
const car = {
name: "Porshe Cayenne",
equipment:{
engine: "MDC.AB"
}
} as const;
car.equipment.engine = "F8CV"; // ERROR: Cannot assign to 'engine' because it is a read-only property.
as const
превосходно подходит в качестве альтернативы enum
.
О минусах enum
можно подробно почитать в этой статье.
Пример перехода кода с enum
на as const
:
Код, с использованием enum
:
enum Wallet {
KEY = "open_door_pls"
};
const openDoor = (key: "open_door_pls") => {
//...
};
openDoor(Wallet.KEY)
Код, переписанный на as const
:
const wallet = {
key: "open_door_pls"
} as const;
const openDoor = (key: "open_door_pls") =>{
//...
};
openDoor(wallet.key);
Ещё одна действительно крутая особенность as const
заключается в том, что использование as const
позволяет быть очень гибким в обращении с ключевым объектом:
const friendsDict = {
Alfred: "101 Pine Road, Toronto, ON M5A 1A1, Canada",
Liam: "777 Sycamore Lane, Tokyo, 100-0001, Japan",
Mia: "666 Willow Street, Paris, 75001, France",
} as const;
type FriendName = keyof typeof friendsDict; // "Alfred" | "Liam" | "Mia"
type FriendAddress = (typeof friendsDict)[keyof typeof friendsDict];
//"101 Pine Road, Toronto, ON M5A 1A1, Canada" | "777 Sycamore Lane, Tokyo, 100-0001, Japan" | "666 Willow Street, Paris, 75001, France"
Мы рассмотрели конструкцию as const
в TypeScript и её роль в создании более строгих и предсказуемых типов данных. Надеюсь, что данная статья помогла вам лучше понять, как использование as const
может повысить уровень безопасности и ясности вашего кода.
Таким образом, внедрение as const
в ваш код может быть ключом к облегчению его поддержки в будущем и уменьшению вероятности ошибок. Пользуйтесь этим инструментом с умом, и ваш код станет более чистым, надежным и легко поддерживаемым!
До новых встреч в мире строгой типизации!