Pull to refresh

Comments 25

Не проще по двум причинам:

1) В таком случае у вас уже есть обычный массив с данными и его можно использовать, как массив во вс\м коде.

2) Мы просто выводим тип из этого массива и этот тип всегда будет синхронизирован с реальными данными в массиве.

По факту эдакая замена enum, но с расширенными структурами данных.

Спасибо за разъяснение - так и есть, можно сделать и иными способами, но я конкретно рассматривал решение с наименьшим количеством кода.

Ну и если массив в будущем будет дополняться, неудобно же все вручную прописывать при помощи enum или type MyType ="first" | "second" | ...

Я б это в статью добавил, хорошие аргументы

Просто если расписывать разницу с enum, статья растянется и это изначально не являлось целью этой статьи.

Приходится повторяться потом:

const arr: MyType[] = ["first", "second", ...];

А почему не использовать enum для этих целей?

Можно и enum, но я конкретно рассматривал решение с наименьшим количеством кода.

Ну и если массив в будущем будет дополняться, нам придется в enum еще лезть и дополнять все вручную.

Так же как и в вашем случае, тоже придется дополнить варианты возможных значений))

Я это делаю один раз на месте в массиве

С enum вот так например:

enum NumberNamesEnum {
  First = "first", 
  Second = "second", 
  Third = "third", 
  Fourth = "fourth", 
  Fifth = "fifth", 
}

const numberNames: NumberNamesEnum[] = [
  NumberNamesEnum.First, 
  NumberNamesEnum.Second, 
  NumberNamesEnum.Third, 
  NumberNamesEnum.Fourth, 
  NumberNamesEnum.Fifth, 
];

И это все надо держать в актуальном состоянии, и потом чтоб использовать - импортировать везде.
Но с другой стороны такое выглядит лучше задокументированным и в сравнении с моим решением не нужно голые строки везде использовать.

Конкретно в этом случае можно сделать:

const numberNames: NumberNamesEnum[] = Object.values(NumberNamesEnum);

но если сделать "const enum", то так уже не получится.

Пожалуйста, не надо использовать енумки в качестве объектов. Они не предназначены для этого.

Вы здесь пользуетесь тем, что этот конкретный энум содержит только строковые значения. Если бы среди значений были числовые, то Object.values перечислил бы значения как прямого отображения, так и обратного, а тайпскрипт бы ругнулся, что тип переменной numberNames не принимает строки, которые результат функции Object.values будет содержать. Подход же, предложенный автором статьи, годится как для строковых (или смешанных) энумов, так и для числовых.

Как минимум один плюс: для передачи литерала в качестве параметра вам не нужно дополнительно импортировать enum и искать, откуда его импортировать.

enum очень ужасен, аж один из разработчиков тайпскрипта говорил что есои бы пришлось изобретать enum сейчас то они не стали бы это делать.
Вместо enum многие (и я) пользуются объектами с последующим `keyof typeof numberNames`

Да, в случае с объектом так и есть

Кроме того, если значения отличны от ключей, то можно ещё определить следующий тип:
type NumberValue = typeof numberNames[NumberName];
И вуаля — энумы не нужны!

А может еще добавите в статью, в какой версии TypeScript появилась возможность вот так использовать "индексатор числа [number]". Это может быть полезно для тех, кто внимательно следил за TypeScript раньше, а сейчас немного ослабил хватку :)

Хорошая идея. Спасибо! Добавил инфу в пост.

Спасибо. Рад в кое-то веке видеть небольшую, но информативную техническую статью на хабре.

Так же хочу показать ещё один интересный пример:

const args = [8, 5] as const;
const angle = Math.atan2(...args);

Так как к массиву применен as const его длинна известна на стадии компиляции. Функция Math.atan2 принимает только два аргумента, и, так как компилятор знает о длине массива, позволяет использовать spread-оператор. Если убрать as const, то компилятор не будет знать о длине массива, и не разрешит такой вызов.

Круто, мне понравилось использование таким образом

Удивительно, что на две бытовых строчки кода такая объемная статься вышла. И название такое, что думал что-то необычное увидеть

Но совсем уж начинающим может пригодиться, жаль, что такую статью через Гугл не найти, слишком сложное для этого название. На вашем месте, я бы упростил

Кому интересно, какие плюсы у этого подхода:

  1. Если смотреть фронтенд - не надо импортить везде как enum, и что ещё хуже добавлять в контекст компонента для того, чтобы он попал в рендер (привет vue2)

  2. Удобно описать валидатор для конечной точки в цепочке компонентов (функций). В цепочке проверяем тип (и удобно указываем значения), в конце проверяем, что никто не навлевал на требуемый тип, ибо ts не гарантия :)

Я гуглил и смотрел какой перевод у понятия type inference. Везде было "Вывод типов". Решил так и использовать, хотя может можно было что-то типа "Вычисление типа по массиву строковых значений".

Статья вышла в таком объёме, в каком я сам решил для аудитории тех, кто с таким подходом не знаком, с одной стороны стараясь не поливать воду, а с другой стараясь ничего не пропустить и простым языком дать объяснение.

Sign up to leave a comment.

Articles