3 ms·
I like to make the 'brand' property optional so that it doesn't actually have to be there at runtime, but the TypeScript type-checker will still catch mismatche
by TOGoS 2y ago
I like to make the 'brand' property optional so that it doesn't actually have to be there at runtime, but the TypeScript type-checker will still catch mismatches
type USDollars = number & { currency?: "USD" }
(or something like that; My TypeScript-fu may be slightly rusty at the moment.)
Of course a `number` won't have a currency property, but if it did, its value would be "USD"!
I've found that TypeScript's structural typing system fits my brain really well, because most of the time it is what I want, and when I really want to discriminate based on something more abstract, I can use the above trick[1], and voila, effectively nominal types!
[1] With or without the tag being there at runtime, depending on the situation, and actually I do have a lot of interface definitions that start with "classRef: " + some URI identifying the concept represented by this type. It's a URI because I like to think of everything as if I were describing it with RDF, you see.
(More of my own blathering on the subject from a few years ago here: http://www.nuke24.net/plog/32.html http://www.nuke24.net/plog/32.html)
- williamdclt 2y agoMaking it optional doesn't work, the brand property needs to be required. Doesn't mean that you actually have to define the property at runtime, you'd usually cast the number to USDollars where relevant
- TOGoS 2y agoAccording to Deno it does work. type USD = number & { currency?: "USD" } type CAD = number & { currency?: "CAD" } const fiveUsd : USD = 5; const fiveCad : CAD = fiveUsd; console.log("How many CAD? " + fiveCad); Results in an error, Type '"USD"' is not assignable to type '"CAD"'. If by "doesn't work" you mean that the implicit number->USD conversion is allowed, then I disagree with the judgement, as that is by design. But once the values are in variables of more specific types, the type-checker will catch it.