Suggestion: add generic tagged objects to core library
SimonMeskens opened this issue · 1 comments
A lot of suggestions have been around nominal typing. A fair share of those are made by people who are pleasantly surprised to discover the tagged interface method. I propose adding @RyanCavanaugh's elegant generic solution to the library (and the documentation!), to help users discover this great feature. It would also avoid every popular Typescript library eventually adding their own version of this. I know I was surprised to find it and I would have loved to discover it sooner.
type Branded<T, U> = T & { [Symbol.species]: U };Example use:
// UUID or a symbol, once symbol literal types are supported
type OrderUUID = "d3a8e9b5-07c2-4a2d-a245-8a5908826b0f";
// Tagged Alias
type OrderID = Branded<string, OrderUUID>;It may be useful to split this into a type and an interface, though this may make it less elegant (and thus overreaching for inclusion in the core library):
interface Specified<T> {
[Symbol.species]: T;
}
type Branded<T, U> = T & Specified<U>;It does allow for more advanced uses of this system, such as runtime type checking:
// Is there a more elegant way to get a string literal type?
const OrderUUID = "d3a8e9b5-07c2-4a2d-a245-8a5908826b0f" as "d3a8e9b5-07c2-4a2d-a245-8a5908826b0f";
// Tagged Class
class Order implements Specified<typeof OrderUUID> {
[Symbol.species] = "d3a8e9b5-07c2-4a2d-a245-8a5908826b0f" as typeof OrderUUID;
}
function isOrder(arg: any): arg is Order {
return OrderUUID in arg;
}The naming might need some discussion.
We've kicked this idea around a bunch of times and have opted to look into built-in solutions instead of adding types to the lib.