Earlier quoted context omitted.
I see where you are coming from but you are not quite understanding what the OP was saying class A { public value: number } class B { public value: number } const x: A = new B() // no error This is structural typing (shape defines type), if typescript had nominal typing (name defines type) this would give an error. You could brand these classes to forcefully cause this to error. Branding makes structural typing work…
> Branding makes structural typing work like nominal typing for the branded type only. That's not quite true. Branding doesn't exist at run time, where as nominal typing usually does at some level. Classes exist at runtime, but most typescript types don't, so unless there's something specific about the shape of the data that you can check with a type guard, it's impossible to narrow the type.
Branded types for TypeScript
91–100 of 152 posts
Re: Branded types for TypeScript
#92Re: Branded types for TypeScript
#93Earlier quoted context omitted.
Can you say more about natively supporting discriminated unions? You can already do this: type MyUnion = { type: "foo"; foo: string } | { type: "bar"; bar: string }; And this will compile: (u: MyUnion) => { switch (u.type) { case "foo": return u.foo; case "bar": return u.bar; } }; Whereas this wont: (u: MyUnion) => { switch (u.type) { case "foo": return u.bar; case "bar": return u.foo; } };
Sure! You need a `type` field (or something like it) in TS. You don't need that in a language like F# -- the discrimation occurs strictly in virtue of your union definition. That's what I meant by "native support."
type MyUnion = { type: "foo"; foo: string } | { type: "bar"; bar: string };
vs type MyUnion = Foo of { foo: string } | Bar of { bar: string };
You still need some runtime encoding of which branch of the union your data is; otherwise, your code could not pick a branch at runtime.There's a slight overhead to the TypeScript version (which uses strings instead of an int to represent the branch) but it allows discriminated unions to work without having to introduce them as a new data type into JavaScript. And if you really wanted to, you could use a literal int as the `type` field instead.
Re: Branded types for TypeScript
#94It took me so long to fully appreciate TypeScript's design decision for doing structural typing vs. nominal typing. In all scenarios, including the "issue" highlighted in this article there is no reason for wanting nominal typing. In this case where the wrong order of parameters was the issue, you can solve it with [Template Literal Types]( https://www.typescriptlang.org/docs/handbook/2/template-lite... ). See [1]. A…
You can solve the issue in this particular example because the "hashing" function happens to just append a prefix to the input. There is a lot of data that isn't shaped in that manner but would be useful to differentiate nonetheless.
> And for `hash.toUpperCase()`, it's a valid program.
It's odd to try and argue that doing uppercasing a hash is okay because the hash happens to be represented as a string internally, and strings happen to have such methods on them. Yes, it's technically a valid program, but it's absolutely not correct to manipulate hashes like that. It's even just odd to point out that Typescript includes string manipulation methods on strings. The whole point of branding like this is to treat the branded type as distinct from the primitive type, exactly to avoid this correctness issue.
Re: Branded types for TypeScript
#95I had the displeasure of working with a Flow codebase that typed every string and int uniquely like this. I could see the benefit if you’re working on something mission critical where correctness is paramount, but in your average web app I think it just creates a lot of friction and busy work with no real benefit.
Re: Branded types for TypeScript
#96Earlier quoted context omitted.
The point of branded types is, among other things, that you do not need to introduce a wrapper class which consumes additional memory.
Are you worried about compiler memory consumption? Because it's not a class, it's a type, and it's erased at compile time.
Re: Branded types for TypeScript
#97Earlier quoted context omitted.
The point of branded types is, among other things, that you do not need to introduce a wrapper class which consumes additional memory.
Really? I'm surprised you mention memory is even a consideration, never even heard it raised as far as typing choices are concerned.
Re: Branded types for TypeScript
#98These are sometimes called "strong" or phantom types in other languages, e.g.: https://github.com/mapbox/cpp/blob/master/docs/strong_types....
https://package.elm-lang.org/packages/ianmackenzie/elm-units...
Very nice to prevent conversions between incompatible units, but without the over head of lots of type variants.
https://thoughtbot.com/blog/modeling-currency-in-elm-using-p...
Re: Branded types for TypeScript
#99As someone who values a tight domain model (a la DDD) and primarily writes TypeScript, I've considered introducing branded types many times, and always decline. Instead, we just opt for "aliases," especially of primatives (`type NonEmptyString = string`), and live with the consequences. The main consequence is that we need an extra level of vigilance and discipline in PR reviews, or else implicit trust in one another…
That's not quite what ends up happening in this article though. The actual objects themselves are left unchanged (no new fields added), but you're telling the compiler that the value is actually an intersection type with that unique field. There a load-bearing `as Hash` in the return statement of `generateHash` in the article's example that makes it work without introducing runtime overhead.
I definitely agree about native support for discriminated unions / nominal typing though, that would be fantastic.
Re: Branded types for TypeScript
#100I had the displeasure of working with a Flow codebase that typed every string and int uniquely like this. I could see the benefit if you’re working on something mission critical where correctness is paramount, but in your average web app I think it just creates a lot of friction and busy work with no real benefit.