Live data from Hacker News

TypeScript: Branded Types

prosopo.io

101–110 of 209 posts

Re: TypeScript: Branded Types

#101

Earlier quoted context omitted.

Could’t one write a TypeScript runtime in JavaScript or WASM?

It 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.

Does branding work in AssemblyScript?

Re: TypeScript: Branded Types

#102

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)?

A lot of code may end up dealing with multiple kinds of IDs at the same time.

For Rust I wrote newtype-uuid to provide newtype wrappers over UUIDs, which has already found a couple of bugs at Oxide.

[1] https://crates.io/crates/newtype-uuid

Re: TypeScript: Branded Types

#104

Anytime I’ve come across the need to do this, I’ve found a class is a better and less complicated solution. 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…

> As far as I understand classes are the only real way to get nominal typing in TypeScript.

Although classes and instances are ultimately structural, right?

    let foo = new Foo();
    assert(foo.constructor == Foo);

Re: TypeScript: Branded Types

#105
post #95

Earlier quoted context omitted.

> If this is something you need, it smells like "runtime checking" not amending the type system. This is both! The primary point of branded types is to allow you to use the type system to ensure that a particular runtime check has taken place.

> The primary point of branded types is to allow you to use the type system to ensure that a particular runtime check has taken place. I see. This is kind of cool, though the branding can still be broken via down-the-stream mutations. Would be nice to enforce re-branding every time a variable is changed, but that seems like a lot of overhead.

> the branding can still be broken via down-the-stream mutations

Only for mutable values! A branded string should be as immutable as they come, right?

Re: TypeScript: Branded Types

#106

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.

Typescript is not a real standalone language. It's just javascript after all.

Try Dart, maybe you like it. It's like TS but with it's own runtime.

Re: TypeScript: Branded Types

#107

Anytime I’ve come across the need to do this, I’ve found a class is a better and less complicated solution. 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…

> Anytime I’ve come across the need to do this, I’ve found a class is a better and less complicated solution ... As far as I understand classes are the only real way to get nominal typing in TypeScript.

How are classes going to help? As far as I understand TS is structural period. Ex this is valid (!):

  class Email {
      constructor(public email: String) {}
  }
  let x: Email = new Email('foo@foo.com')
  let y = { email: '73'}
  x = y;

Re: TypeScript: Branded Types

#109
Isn't this just the classic issue of inferred typing coming back to bite us in the way everyone originally predicted? Go runs into the same issue where wildly different types may be considered the same based purely on coincidental naming and matching against interfaces the original authors had no intent to match against. At the end of the day I think the easier system to work with is one in which all type compatibility needs to be explicitly declared - if your array is iterable defining that it implements iterable lets your compiler shout at you if iterable suddenly gets another abstract method that you didn't implement - and it makes sure that if you add a method `current` to a class it doesn't suddenly means that it properly supports iterable-ity.

Determining types by what things appear to do instead of what they state they do seems like a generally unnecessary compromise in typing safety that isn't really worth the minuscule amount of effort it can save.

Re: TypeScript: Branded Types

#110

Earlier quoted context omitted.

Classes are very underutilised in TypeScript. I recently introduced them to our codebase at my day job and got a fair bit of pushback because it wasn’t “JavaScripty” enough.

That's a weird objection, because Typescript classes are literally Javascript classes[1]. [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

There was plenty of outrage when classes were added to JS. “JS uses prototypal inheritance, not OOP!”
Post reply on HN