Как лучше оформлять и использовать перечисления и типы в ts?
По вводным: при написание имени перечисления, я заискал в поиске, как его правильно оформить, пишут разное, использовать для перечислений "Screaming Snake Case" (ENUMПо вводным:), использовать множественное числоEnumsПо вводным:, использовать обычное название Enum, но писать тип в формате EnumType или TEnum. Но чаще встречается вариант с использованием одного и того же имени Enum в обоих случаях.
По вводным: в качестве примера, создал 2 файла, один с перечислением и типами другой с использованием этих сущностей.
// types.ts export const Enum = { a: 'a', b: 'b', } as const; export type Enum = typeof Enum[keyof typeof Enum];
// functions.ts import { Enum } from './test.js'; function fn(areas: Enum): Enum { switch (areas) { case Enum.a: return Enum.a; case Enum.b: default: return Enum.b; } }
Нужно понять: какие форматы названий используете вы? А если там еще интерфейс, то писать IEnum? А если схема из zod, то писать EnumSchema? Тогда почему I идет вначале, а Schema в конце?
export const Enum = { a: 'a', b: 'b', } as const; export const EnumSchema = z.enum(Enum);
Нужно понять: и вопрос по zod, если планируется его использовать в проекте и в других местах, то нормально ли писать сразу так?
// export type Enum = typeof Enum[keyof typeof Enum]; export type Enum = z.infer<typeof Enum>;
P.S. Используюconst as const, т.к:
НаПо вводным: tSConf 2020: TalkScript with the TypeScript TeamСейчас ситуация такая: создателями TS было сказано примерно следующее: - вам следует избегать перечислений в TypeScript. Они являются ошибкой языка (как отметили создатели), поскольку противоречат целям TypeScript как системы типов и не вносят дополнительных функций во время выполнения. Мы также глубоко верим в обратную совместимость. Мы никогда не отменим то, что уже внедрили.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
В TypeScript нормальная практика — не плодить префиксы
I,T,EnumTypeбез необходимости. Имя должно описывать предметную область, а не технический тип. Если у Вас объект значений и union type из его значений, вариант с одинаковым именем в value-space и type-space допустим и часто используется.Ваш пример:
export const Area = { A: 'a', B: 'b', } as const; export type Area = typeof Area[keyof typeof Area];export const Area = { A: 'a', B: 'b', } as const; export type Area = typeof Area[keyof typeof Area];
Это нормально:
Areaкак значение используется в runtime, аAreaкак type используется только на этапе типизации. TypeScript разделяет эти пространства имён.Я бы не называл сущность просто
Enum. Лучше предметно:UserRole,OrderStatus,PaymentMethod,Area. Множественное число обычно не нужно, потому что тип описывает одно значение:UserRole, а неUserRoles.Для строковых наборов сейчас часто используют объект
as const, а неenum:export const OrderStatus = { Draft: 'draft', Paid: 'paid', Cancelled: 'cancelled', } as const; export type OrderStatus = typeof OrderStatus[keyof typeof OrderStatus];export const OrderStatus = { Draft: 'draft', Paid: 'paid', Cancelled: 'cancelled', } as const; export type OrderStatus = typeof OrderStatus[keyof typeof OrderStatus];
Плюсы: проще tree-shaking, меньше магии runtime, удобнее совместимость с JSON/API.
Интерфейсы с префиксом
I— дело стиля команды. В современных TS-проектах чаще пишут без префикса:interface User { id: string; role: UserRole; }interface User { id: string; role: UserRole; }
Если в проекте уже принят стиль
IUser, лучше придерживаться его. Но в новом коде я бы не вводил венгерскую нотацию.Итог: используйте предметные имена в единственном числе. Для union из объекта
as constодинаковое имя const и type — нормальный TS-паттерн. Главное — не называть всё абстрактноEnum, а давать имя по смыслу.