basarat / basarat/typescript-book
Should not suggest Enums to implement Brands
- 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
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