Ah, the magical disappearing type system - now being used for nominal typing. I'm curious to see what the JS code looks like for casts and type checks in that case.
More like: magical disappearing type system is not nominal: hacky workarounds ensue.
71–80 of 209 posts
Ah, the magical disappearing type system - now being used for nominal typing. I'm curious to see what the JS code looks like for casts and type checks in that case.
More like: magical disappearing type system is not nominal: hacky workarounds ensue.
Earlier quoted context omitted.
I don't see why. I greatly prefer typescript's structural typing for almost everything. But id's in data models are an exception, so I use branding for those. It works perfectly, the only overhead is in the write-once declaration and now I am protected from accidentally using an AccountId where a MemberId was expected, even though they are both just strings.
How do ids of different types accidentally get into a place they shouldn't be? Is this simply a case where someone mistakenly passes along a property that happens to be called "id", not noticing it's an account id rather than a member id (as in, an implementation error)?
I can see this being useful and it seems about as neat a solution as you can currently get in TypeScript as it stands today, but it’s still cumbersome. My feeling is that while you can do this, you’re swimming upstream as the language is working against you. Reaching for such a solution should probably be avoided as much as possible.
Rather, I think Typescript's philosophy of not having a runtime is simply wrong. Other statically typed languages retain type information at runtime. I don't understand why that was so important to explicitly exclude from Typescript.
Weird idea, as types in TS are structural by design . If this is something you need, it smells like "runtime checking" not amending the type system.
Design doesn’t cover all use cases. There’s nothing weird about wanting different types for “user id” and “organisation id” so that you don’t use the wrong argument by mistake
Earlier quoted context omitted.
Design doesn’t cover all use cases. There’s nothing weird about wanting different types for “user id” and “organisation id” so that you don’t use the wrong argument by mistake
While you're right that branding makes passing arguments more ergonomic, I will still always be able to do `as OrgId` or `as UserId` so you need to do have some failure handling anyway, unless you're okay with blowing up in the user's face.
Or perhaps I'm misunderstanding your comment. When you do `as OrgId` or `as UserId`, where do you envision those casts in ways that would require handling failures?
Weird idea, as types in TS are structural by design . If this is something you need, it smells like "runtime checking" not amending the type system.
I really like the pattern of value objects from Domain Driven Design. Create a class that stores the value, for example email address.
In the class constructor, take a string and validate it. Then anywhere that you need a valid email address, have it accept an instance of the Email class.
As far as I understand classes are the only real way to get nominal typing in TypeScript.
Earlier quoted context omitted.
Yes, ts is full of this kind kind of adhoc-ifs-like glued together, also exactness check only when it's literal object etc. Flow is more principled.
I mean. I think this specific case is a lot more principled than you seem to think. It’s certainly well reasoned from a perspective of structural typing by default.
It doesn't change the fact that ie. adding private member is breaking change in your library which is kind of funny (until it's not funny of course).
Also stuff like:
class Foo { private foo = 1 }
class Bar {}
const a: Bar = new Foo
...typechecks so that's it for nominality.It's all ifs all the way down.