As const в Typescript

от автора

Привет, Хабр!

В разработке часто возникают ситуации, когда точность типов и нежелание допускать неясности в коде становятся первостепенными задачами. В таких случаях, разработчикам приходится искать инструменты, предоставляющие максимальную ясность и строгость в определении данных. Один из таких инструментов — ключевое слово as const. В данной статье мы рассмотрим, как 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()?

Проблема 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.

Замена enum-ам?

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 в ваш код может быть ключом к облегчению его поддержки в будущем и уменьшению вероятности ошибок. Пользуйтесь этим инструментом с умом, и ваш код станет более чистым, надежным и легко поддерживаемым!

До новых встреч в мире строгой типизации!

Ещё полезностей по теме

as const: the most underrated TypeScript feature

Enums considered harmful

Use ‘as const’ in TypeScript


ссылка на оригинал статьи https://habr.com/ru/articles/784862/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *