Amazing, we have invented nominal typing in a structural typing system. Sometimes I wonder what kind of programs are written using all these complicated TS types. Anecdotally, we use very simple, basic types in our codebase. The need for tricks like this (and other complicated types) is simply not there. Are we doing something wrong?
I think the example could be better in this article. Let's say you have a function that takes a database id, an email address, and a name. They're all strings. If you pass arguments to this function and you mess up the order for some reason then the compiler has no idea. Hopefully your unit tests catch this but it won't be as obvious. Branded types solve this problem because you can't pass a name string as an argumen…
TypeScript: Branded Types
21–30 of 209 posts
Re: TypeScript: Branded Types
#22Re: TypeScript: Branded Types
#23To me the real benefit of branded types is for branded primitives. That helps you prevent mixing up things that are represented by the same primitive type, like say relative and absolute paths, or different types of IDs. You really don't need the symbol - you can use an obscure name for the branding field. I think it helps the type self-document in errors and hover-overs if you use a descriptive name. I use branding…
Re: TypeScript: Branded Types
#24To me the real benefit of branded types is for branded primitives. That helps you prevent mixing up things that are represented by the same primitive type, like say relative and absolute paths, or different types of IDs. You really don't need the symbol - you can use an obscure name for the branding field. I think it helps the type self-document in errors and hover-overs if you use a descriptive name. I use branding…
const accountId: Brand = "123654"
Has the error Type 'string' is not assignable to type '{ readonly __Account_brand: never; }'Re: TypeScript: Branded Types
#25To me the real benefit of branded types is for branded primitives. That helps you prevent mixing up things that are represented by the same primitive type, like say relative and absolute paths, or different types of IDs. You really don't need the symbol - you can use an obscure name for the branding field. I think it helps the type self-document in errors and hover-overs if you use a descriptive name. I use branding…
Sorry, how do you apply it to branding primitives? The basic const accountId: Brand = "123654" Has the error Type 'string' is not assignable to type '{ readonly __Account_brand: never; }'
You have to make a function to apply the brand via a cast, the article explains this as well.
function makeObjectId(id: string): ObjectId {
return id as ObjectId;
}Re: TypeScript: Branded Types
#26Earlier quoted context omitted.
Sorry, how do you apply it to branding primitives? The basic const accountId: Brand = "123654" Has the error Type 'string' is not assignable to type '{ readonly __Account_brand: never; }'
This error is, in fact, the point. It keeps you from accidentally assigning a normal string to a branded string You have to make a function to apply the brand via a cast, the article explains this as well. function makeObjectId(id: string): ObjectId { return id as ObjectId; }
const accountId = "125314" as AccountId
It makes sense that the technique uses casting.Re: TypeScript: Branded Types
#27To me the real benefit of branded types is for branded primitives. That helps you prevent mixing up things that are represented by the same primitive type, like say relative and absolute paths, or different types of IDs. You really don't need the symbol - you can use an obscure name for the branding field. I think it helps the type self-document in errors and hover-overs if you use a descriptive name. I use branding…
Re: TypeScript: Branded Types
#28Earlier quoted context omitted.
Yes you can, it works just the same :-)
Sorry, with the Symbol? How does it work?
type Velocity = number & { BRAND: "Velocity" }
type Distance = number & { BRAND: "Distance" }
var x = 100 as DistanceRe: TypeScript: Branded Types
#29Amazing, we have invented nominal typing in a structural typing system. Sometimes I wonder what kind of programs are written using all these complicated TS types. Anecdotally, we use very simple, basic types in our codebase. The need for tricks like this (and other complicated types) is simply not there. Are we doing something wrong?
You don't use them but your favorite libraries do.
Data validation, typed database access, or functional programming libraries are good examples. Particularly the modern, leading libraries of such areas, if you look into their code you'll generally see very intricate typing. For FP libraries it's particularly tough. I like to use Remeda which emphasizes being very type-safe, but that means it's inherently more limited in what functions it can offer compare to other libraries which choose to compromise their type-safety. These kinds of techniques mean that libraries can offer greater functionality while remaining type-safe.
Re: TypeScript: Branded Types
#30The article reads more like an endorsement of languages that do structurally-aware nominal typing (that is, languages that are nominally typed but that have awareness of structural equivalence so that zero-cost conversions and intelligible compile-time errors for invalid conversions are first class) than a persuasive case for the symbol-smuggling trick described.