typescript-book
typescript-book copied to clipboard
Should not suggest Enums to implement Brands
Enums should not be suggested as a branding mechanism because they will be normalised away in union types. The current example:
// 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:
const test: 10 = Math.random() > 0.5 ? 10 : barId;
Or this usage:
const test2: never = Math.random() > 0.5 ? fooId : barId;
These are both unsafe!
The issue is that the types expand as:
/*
For example `test`
(10 | BarId) ====> 10 | (BarIdBrand & string)
Empty literal intersections in unions reduce to never.
(10 | (BarIdBrand & string)) ====> (10 | never) ====> 10
*/
Nice analysis. Note to self:
/*
For example `test2`
(FooId | BarId) ====> (FooIdBrand & string) | (BarIdBrand & string)
Empty literal intersections in unions reduce to never.
((FooIdBrand & string) | (BarIdBrand & string)) ====> (never | never) ====> never
*/
Note to self Review: https://github.com/Microsoft/TypeScript/issues/202