basarat / basarat/typescript-book

Should not suggest Enums to implement Brands

Open
#492 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
21.6k
Forks
2.6k
PR merge metrics
No merged PRs in 30d

Description

Enums should not be suggested as a branding mechanism because they will be normalised away in union types. The current example:
```ts
// FOO
enum FooIdBrand {}
type FooId = FooIdBrand & string;

// BAR
enum BarIdBrand {}
type BarId = BarIdBrand & string;

/**
* Usage Demo
*/
var fooId: FooId;
var barId: BarId;

// Safety!
fooId = barId; // error
barId = fooId; // error

// Newing up
fooId = 'foo' as FooId;
barId = 'bar' as BarId;

// Both types are compatible with the base
var str: string;
str = fooId;
str = barId;
```
Consider this usage:
```ts
const test: 10 = Math.random() > 0.5 ? 10 : barId;
```
Or this usage:
```ts
const test2: never = Math.random() > 0.5 ? fooId : barId;
```
These are both unsafe!

The issue is that the types expand as:
```ts
/*

For example `test`

(10 | BarId) ====> 10 | (BarIdBrand & string)

Empty literal intersections in unions reduce to never.

(10 | (BarIdBrand & string)) ====> (10 | never) ====> 10

*/
```

Contributor guide

Open the contributing guide

Research direction

Start by locating the branding documentation that contains the enum-based FooId and BarId examples. Review the examples against the unsafe union cases described in the issue, and consider the documentation complete when it no longer suggests enums as a safe branding mechanism.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.