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 </>
npm i enum-object-value -S
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.
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);
// 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
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'] },
);
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"];
// };
// }
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"];
// } |
// ...
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());