4 ms·
FYI, TypeScript already supports nominal types, but the ways in which you "spell" `nominal` are a little unintuitive: 1. Use an enum 2. Use an intersection wi
by svieira 4y ago
FYI, TypeScript already supports nominal types, but the ways in which you "spell" `nominal` are a little unintuitive:
1. Use an enum
2. Use an intersection with an enum and literally anything else (except a number)
3. Use a private field (only works with classes)
4. Use a `declare const FOO: unique symbol` keyed object intersected with anything else (works with everything including numbers, lots of boilerplate to declare a new nominal type).
- ajkjk 4y agoI'm aware of some of those, but I think they're all suboptimal compared to actual nominal types. In particular iirc you can't use your nominal/branded type as a map key in a type-safe way.
- scotty79 4y agoNot sure what you mean: enum A {} type B = { a: number } & A; function newB(i:number) { return { a: i } as B; } let b:B = newB(5); let m:Map<B, string> = new Map(); m.set(b, "test"); m.set({ a: 2 }, "test"); // errors
- svieira 4y agoWhat he means is that you didn't _used_ to be able to do this: declare const NOMINAL_BRAND: unique symbol; enum UserIdType {} type UserId = string & {[NOMINAL_BRAND]: UserIdType} type UserMap<V> = { [key: UserId]: V }; But at some point in the past few years, this is now supported and things like this work as expected: const userId: UserId = "234" as UserId const coolUsers: UserMap<boolean> = {} coolUsers[userId] = true // works coolUsers["isThisOkay"] = false // fails
- ajkjk 4y agoInteresting, I thought that wasn't possible, but now I feel like I'm just confused and mixing it up with something else that wasn't possible but can't remember well enough. But anyway, what I want from TS is type UserId = unique string; // or something const userId = "1234" as UserId and no further boilerplate or trickery to get it to work. Would certainly be nice.
- scotty79 4y agoYou can get close to that: https://github.com/seancroach/ts-opaque https://github.com/seancroach/ts-opaque
- no_wizard 4y agoyou could use a WeakMap to emulate private fields too