6 ms·
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 feel
by jonathanlydall 3y ago
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.
- shadowgovt 3y ago> as the language is working against you Right, but this is one of those situations where a reasonable person could conclude "The language is not working to help me solve the problem I'm trying to solve." Sometimes you don't want JavaScript sloppiness and you also don't want TypeScript structural-type "sloppiness," desiring instead nominal types. This is a clever way to use the existing infrastructure to get nominal types with no additional runtime overhead.
- kristiandupont 3y agoI 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.
- cush 3y agoYes! I've wanted this in Typescript for ages! Is it possible to brand primitives though?
- kristiandupont 3y agoYes you can, it works just the same :-)
- amatecha 3y agoHow 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)?
- mason55 3y agoYeah, or what's more likely is that you originally used an AccountID everywhere, but then you decided that you want to use a UserAccountID. So you update your functions but you miss a spot when you're updating all your call sites. Or you have a client library that you use to interact with your API, and the client library changes, and you don't even notice. Or you change the return type of a function in a library, and you don't even know who all the callers are, but it sure would be nice if they all get a build error when they update to the latest version of your library. Lots and lots and lots of ways for this to happen in a medium+ sized project that's been around for more than a few months. It's just another way to leverage the power of types to have the compiler help you write correct code. Most of the time most people don't mess it up, but it sure feels good to know that it's literally impossible to mess up.
- klysm 2y agoThis kind of mistake is quite easy to make, especially when somebody writes a function that takes several IDs as arguments next to each other. I've seen it happen a number of times over the years
- z3t4 2y agofunction foo(customerId, itemId, orderId) { if(!customer[customerId]) throw new Error("Customer with id=" + customerId + " does not exist"); if(!item[itemId]) throw new Error("Item with id=" + itemId + " does not exist"); if(!order[orderId]) throw new Error("Order with id=" + orderId+ " does not exist"); } Just an example of how you can detect errors early with defensive programming.
- antifa 2y ago
- jrockway 3y agoRather, 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.
- nosefurhairdo 3y agoIf we needed a special Typescript runtime to use Typescript it would become nearly useless. The vast majority of Typescript becomes JavaScript running in Node or V8. The web is stuck with JavaScript, and Typescript is a tool to help us write maintainable JavaScript.
- williamcotton 3y agoCould’t one write a TypeScript runtime in JavaScript or WASM?
- kevingadd 2y agoIt wouldn't be very useful, since a TS-in-JS runtime would have significant performance overhead, and a TS-in-WASM runtime would have very expensive JS interop plus cross-language-GC hurdles. Might be less bad with WASM GC.
- DonHopkins 2y agoDoes branding work in AssemblyScript?
- moritzwarhier 2y agoWith horrible overhead, and in the case of WASM, lots of serialization and API glueing (DOM is just somewhere near the tip of the iceberg) woes, maybe? Would be a fun thing to do for sure, but never as fast as the APIs built into the browser runtime.
- DanielHB 2y agoUsing any JIT language (most implementations of python, Java, ruby, JS, etc) in WASM means porting the runtime to WASM and then having the runtime (in WASM) parse and JIT-compile your code incurring a double-whammy of performance degradation (WASM runtime compiling your JIT language runtime and then your JIT language runtime compiling your actual code). To do this kind of thing viable there are two ways I can think of: 1) proper ahead-of-time compiler for your language targeting WASM directly. But that means pretty much rebuilding the whole stack for the language as that is a completely different approach. 2) Do something like Android Runtime (ART) does which translates Java bytecode to native machine instructions whenever you install an android app. But in this case translate the bytecode to WASM and do it before distribution. This requires a new compiler-backend which is still quite complex. Both of these mean you don't have a language runtime at all. There is a reason most WASM stuff you see is in written C/C++/Rust and it is not just the lack of GC.