typescript-enum
A set of missing helpers to work with TypeScript enums, providing both runtime and compile-time safety. These helpers cover both string enums and numeric enums.
Installation
npm i typescript-enum
Usage
enumValues - converts an enum to an iterable list:
import { enumValues } from 'typescript-enum'
enum Color { R, G, B }
console.log(enumValues(Color))
isEnumValid - checks if a value is a member of the enum:
import { enumValues } from 'typescript-enum'
enum Color { R, G, B }
const maybeColor = 0;
const notColor = 999;
console.log(isEnumValid(maybeColor, Color));
console.log(isEnumValid(notColor, Color));
if (isEnumValid(maybeColor)) {
}
Use cases
1. You have a list based on enum values.
Before:
❌ The following component should be updated whenever a new member is added to the enum.
enum Permission { Read = 0, Write = 1, Edit = 2 }
const Component = () => {
return <List>
{[Permission.Read, Permission.Write, Permission.Edit].map(permission => {
// Render checkbox to edit permission
})}
</List>
}
❌ The following works only for string enums but won't work for numeric enums because the enum gets transpiled to {"0": "Read", "1": "Write", "2": "Edit", "Read": 0, "Write": 1, "Edit": 2 }. Notice duplicated values.
enum Permission { Read = 0, Write = 1, Edit = 2 }
const Component = () => {
return <List>
{Object.entries(Permission).map(permission => {
// The enum values are duplicated :(
})}
</List>
}
After:
✅ The following component doesn't need to be updated whenever a new member is added to the enum. It also works with both string and numeric enums.
import { enumValues } from 'typescript-enum'
enum Permission { Read = 0, Write = 1, Edit = 2 }
const Component = () => {
return <List>
{enumValues(Permission).map(permission => {
// Render checkbox to edit permission
})}
</List>
}
2. You want to make sure that an unknown value is a member of the enum.
Before:
❌ The following code requires an unsafe type cast.
enum PackageType { Basic, Advanced, Premium }
const packageInput: { type: number } = { type: 0 }
function processPackage(packageType: PackageType) {
}
processPackage(packageInput.type as any)
✅ The following code validates an unknown value both at runtime and compile time.
import { isEnumValid } from './isEnumValid'
enum Package { Basic, Advanced, Premium }
const packageInput: { type: number } = { type: 0 }
function processPackage(packageType: PackageType) {
}
if (!isEnumValid(packageInput.type, Package)) {
throw new Error()
}
processPackage(packageInput.type)
As you can see, the type inference works correctly now, and the type cast is no longer needed. You can even go further and use an assertion library:
import { isEnumValid } from './isEnumValid'
import { assert } from 'ts-essentials'
enum Package { Basic, Advanced, Premium }
const packageInput: { type: number } = { type: 0 }
function processPackage(packageType: PackageType) {
}
assert(isEnumValid(packageInput.type, Package))
processPackage(packageInput.type)