Live data from Hacker News

TypeScript: Branded Types

prosopo.io

191–200 of 209 posts

Re: TypeScript: Branded Types

#191
post #132

Earlier quoted context omitted.

I know what SOLID is, questioning how exactly you think Flow has "liskov substitution" as a feature.

L in SOLID refers to Liskov substitution principles. It's the only one from the SOLID list which can be typechecked - others are design principles. "Flow adhering to it" means that violating code will be flagged by type system. It matters because unlike other principles, violations can cause runtime errors.

> L in SOLID refers to Liskov substitution

you think?

> Flow adhering to it" means that violating code will be flagged by type system

Shocking that type system can flag things

Re: TypeScript: Branded Types

#192
post #133

Earlier quoted context omitted.

how would read only fixes consumers read ing the property?

it doesn't. never prevents reading and readonly prevents (over)writing. GP just focused on the never -part of your question.

never means nothing can be assigned to it, so in that sense it's already readonly

Re: TypeScript: Branded Types

#194

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…

Classes can also make use of the native `instanceof` JavaScript operator [0]. It is also possible to then infer a type from a class so you can use both the class where you want to discriminate types and the type where you really only care about the shape. The absolutism towards OOP/FP -- instead of embracing the right use cases for each -- always ruffles me in the wrong way. C#, for example, does a great job of blend…

JS classes are a great fit for FP. They're just functions with closures and a little syntactic sugar.

Re: TypeScript: Branded Types

#195

An example of what you can implement on top of branded types that I want to share with fellow hackers: - currencies You may have some sort of integer representing the number of cents of some currency and you want to avoid doing operations between the wrong currencies (such as adding euros and pesos). You can create branded types and functions that work on those Euro branded numbers and then decide how to do math on i…

I have seen plenty of currencies come and go in my life: weird to lock that into your codebase.

And I'm struggling to think of where in a codebase I might want to hardcode Pesos or Euros.

Re: TypeScript: Branded Types

#196
post #188

Earlier quoted context omitted.

If you have a function addMemberToOrg(memberId: string, orgId: string), you can accidentally call it like this: addMemberToOrg(myOrgId, myMemberId) and nobody will complain. With branded types, the compiler would mark it as an error.

Function signatures already solve that problem. We have all kinds of functions that take two numbers that mean different things (width/height, x/y, etc.). Branding seems like a solution looking for a problem. I just think it's too much overhead and confusion for too little gain. In fact, a common pattern is to pass fully-qualified objects, e.g. `dimensions = {width: number, height: number}`, which makes mixing up var…

>Function signatures already solve that problem.

I literally just showed you how they don't. And you even go on to describe a pattern that makes the problem "even less likely" in the next sentence..

>Branding seems like a solution looking for a problem.

You do you.

Re: TypeScript: Branded Types

#197

Earlier quoted context omitted.

It's the other way around. Handling difficult cases leads to more type errors. If type system is lax, it won't flag them but they can fail at runtime. React has very little of $FlowFixMe annotations for its codebase. In typescript projects on the other hand it's normal to see unsafety as normal code (casting, non null assertions, implicit and explicit anys etc).

React vs "typescript projects" doesn't seem very fair. React would presumably be the pinnacle of style with respect to flow. Maybe not true, but it's not just some random project. Additionally, I've read a lot of typescript code, and the react codebase. My experience is different than yours. I see more type workarounds in react. FWIW "$FlowFixMe" occurs 822 times in commit hash cf5ab8b8b2c92523aba0b982fb403add053a911…

Yes, it's probably not fair.

I think you're double counting it (original files + emitted files)?

    git clone git@github.com:facebook/flow.git
    grep -roh '$FlowFixMe' flow | wc -l
    423
Yes, it's not easy to grab good stats, my experience is that in ts projects you have much more of explicit type annotations vs flow which has better inference, a lot of type casting (unsafe), implicit and explicit anys (unsafe), null assertions (unsafe), unsafe OO etc.

The code in flow has very interesting feel. Missing explicit type annotations are noticeable, feels like js. Optional names in type signature means functions have very Haskell'ish feel:

    const foo /*: number => string */ =
      x =>
        x.toString()
I use flow in comments so I don't have transpilation. Access to full language means a lot here.

Typescript has some nice things that flow doesn't (ie. template literal types) - but recent activity in flow is very interesting. They've put a lot of effort into making flow understand typescript constructs. Many people don't realize how close they now became.

Even some constructs are implemented first in flow (type guards, in ts scheduled for not yet released v5.5 I believe; NoInfer landed first in flow), then in typescript.

It seems they have opportunity to make flow compatible with typescript enough that you could consume ts typedefs from flow - and when it happens it's definitely going to help opening doors wider for adoption.

[0] https://github.com/search?q=repo%3Afacebook%2Fflow+%24FlowFi...

Re: TypeScript: Branded Types

#198
post #190

Earlier quoted context omitted.

It's very readable if you know what every bit means. export type Brand = T & { readonly [B in Brand as `__${B}_brand`]: never; }; It exports a freshly defined type named Brand, which is a generic type with two parameters, one named T (that can be any type), and other named Brand (probably should be named differently to avoid confusion with the name of the whole exported type). Brand parameter must be a type that's as…

that is WAY too complicated. not to mention using enough of that probably destroyed compile time/interpretation time. every time I see "advanced type logic" it seems to ruin a language, because people dont know how to use it in moderation.

I can't really argue with that. It's a way to get nominal types in a language that has structural typing. Even though the usage is simple, the implementation is more complicated than it should be.

If for example the language was missing builtin hashmap type, its implementation would be nasty as well.

I'm not a huge fan of typing systems, the thing I like the most in TypeScript is that you can use types as little as you want and add more only when you want it. But I don't like languages like go that intentionally lack features.

Re: TypeScript: Branded Types

#199
Is there something wrong with creating opaque types using this method?

  type ObjectId = string & { 
  readonly __tag: unique 
  symbol }
This way, we don't need to use `never`, but we still prevent the creation of a structurally equivalent type by mistake.

Re: TypeScript: Branded Types

#200
post #190

Earlier quoted context omitted.

that is WAY too complicated. not to mention using enough of that probably destroyed compile time/interpretation time. every time I see "advanced type logic" it seems to ruin a language, because people dont know how to use it in moderation.

I can't really argue with that. It's a way to get nominal types in a language that has structural typing. Even though the usage is simple, the implementation is more complicated than it should be. If for example the language was missing builtin hashmap type, its implementation would be nasty as well. I'm not a huge fan of typing systems, the thing I like the most in TypeScript is that you can use types as little as y…

> languages like go that intentionally lack features

people will go as far down the rabbit hole as you let them, which is what the Go developers understand and are trying to account for:

https://www.hyrumslaw.com

Post reply on HN