1.0.0 • Published 1 month ago

enum-object-value v1.0.0

Weekly downloads
-
License
ISC
Repository
github
Last release
1 month ago

Enum Object

Actions Status Coverage

The library for create enum which support object as values. You can simulate enum like Swift associated values or Rust enum with her help. It has supports TypeScript </>

Install

npm i enum-object-value -S

About

Definition of enum in TypeScript can't using object as value.

// ❌ Error
enum UserRole = {
  root = { value: 'root', permission: ['create:admin'] }
}

Library enum-object-value offers a solution to the problem. It make work with enums by analogy associated values in Swift or Rust enum.

Definition

import EnumObject from 'enum-object-value';

const userRoleEnum = new EnumObject({
  ROOT: { value: 'root', permission: ['create:admin', 'create', 'remove', 'read'] },
  ADMIN: { value: 'admin', permission: ['create', 'remove', 'read'] },
  EMPLOYEE: { value: 'employee', permission: ['read'] },
} as const);

Access to properties and names of enum:

// Get value
const admin = userRoleEnum.prop.ADMIN;
// {
//    readonly value: "admin";
//    readonly permission: readonly ["create", "remove", "read"];
// }

// Similarly with method .get
const admin = userRoleEnum.get('ADMIN');

// Get name
const ADMIN = userRoleEnum.name.ADMIN;
// ADMIN

Iteration

for (const [name, { value, permission }] of userRoleEnum) {
  console.log(`${name} => { value: ${value}, permission: ${permission} } }`);
}

// OR
userRoleEnum.forEach((name, { value, permission }) => {
  console.log(`${name} => { value: ${value}, permission: ${permission} } }`);
});

If you want change order of iteration by enum values, you can pass order as optional field of second argument EnumObject:

 const userRoleEnum = new EnumObject(
    {
      ROOT: { value: 'root', permission: ['create:admin', 'create', 'remove', 'read'] },
      ADMIN: { value: 'admin', permission: ['create', 'remove', 'read'] },
      EMPLOYEE: { value: 'employee', permission: ['read'] },
    } as const,
    { order: ['EMPLOYEE', 'ADMIN', 'ROOT'] },
  );

Get names and properties

userRoleEnum.getNames();
// ("ROOT" | "ADMIN" | "EMPLOYEE")[]

userRoleEnum.getValues();
// {
//     readonly ROOT: {
//         readonly value: "root";
//         readonly permission: readonly ["create:admin", "create", "remove", "read"];
//     };
//     readonly ADMIN: {
//         readonly value: "admin";
//         readonly permission: readonly ["create", "remove", "read"];
//     };
//     readonly EMPLOYEE: {
//         readonly value: "employee";
//         readonly permission: readonly ["read"];
//     };
// }

Typings

You can get type of names and values of enum with utility types: EnumNames and EnumValues.

import EnumObject, { EnumNames, EnumValues } from 'enum-object-value';

const data = {
  ROOT: { value: 'root', permission: ['create:admin', 'create', 'remove', 'read'] },
  ADMIN: { value: 'admin', permission: ['create', 'remove', 'read'] },
  EMPLOYEE: { value: 'employee', permission: ['read'] },
} as const;

const userRoleEnum = new EnumObject(data);

type UserRoleEnumNames = EnumNames<typeof userRoleEnum>;
//   "ROOT" | "ADMIN" | "EMPLOYEE"
type UserRoleEnumValues = EnumValues<typeof userRoleEnum>;
// {
//     readonly value: "root";
//     readonly permission: readonly ["create:admin", "create", "remove", "read"];
// } |
// ...

More examples

Examples with functions as values:

import EnumObject, { EnumNames, EnumValues, GetEnumValueByName } from 'enum-object-value';


const paymentTypeEnum = new EnumObject({
  CARD: (number: string, holderName: string, expirationDate: Date) => ({
    type: paymentTypeEnum.name.CARD,
    number,
    holderName,
    expirationDate,
  }),
  GIFT_CERTIFICATE: (number: string) => ({ type: paymentTypeEnum.name.GIFT_CERTIFICATE, number }),
  PAYPALL: (transactionId: string, transactionAuthCode?: string) => ({
    type: paymentTypeEnum.name.PAYPALL,
    transactionId,
    transactionAuthCode,
  }),
} as const);

type PaymentTypeEnumNames = EnumNames<typeof paymentTypeEnum>;
type PaymentTypeEnumValues = ReturnType<EnumValues<typeof paymentTypeEnum>>;

function showInfo(value: PaymentTypeEnumValues) {
  if (value.type === 'CARD') {
    console.log('Card number', value.number);
  } else if (value.type === 'GIFT_CERTIFICATE') {
    console.log('Gift number', value.number);
  } else if (value.type === 'PAYPALL') {
    console.log('Paypal transaction id', value.transactionId);
  }
}

const card = paymentTypeEnum.prop.CARD('234234', 'Peter D', new Date());
showInfo(card);

function getValue<Name extends PaymentTypeEnumNames>(type: Name): GetEnumValueByName<typeof paymentTypeEnum, Name> {
  return paymentTypeEnum.prop[type];
}

const createCard = getValue('CARD');
const card = createCard('11313', 'Peter D', new Date());