-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: brand
Keyword for Structural Branded Types
#61479
Comments
Duplicate of #202. |
@MartinJohns we have the same last name :) My proposal isn’t actually the same. #202 wants true nominal types that don’t behave like their base (e.g. a “nominal string” might not be assignable to string anymore). That’s a much bigger departure from TypeScript’s structural model. My brand keyword is just a lightweight way to keep using the underlying primitive (like number) seamlessly for math or function calls, while preventing accidental assignment between incompatible “brands.” It’s more in line with TypeScript’s existing patterns and addresses the common ID-distinction scenario without forcing nominal typing everywhere. |
That's #202. |
Yeah, I don't think anyone wants branded types that are not assignable to their base types. That doesn't make much sense (may as well use a |
This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
🔍 Search Terms
"brand", "brand type", "branded", "branded types", "structural brand", "tag type"
✅ Viability Checklist
⭐ Suggestion
Add a
brand
keyword to TypeScript for defining structurally branded types based on primitives (e.g.,string
,number
,bigint
). This feature introduces compile-time type distinction without runtime overhead, ensuring that branded types remain structurally compatible with their base types for operations while being distinct in assignment contexts. For example,UserId
andProductId
, both branded fromnumber
, cannot be assigned to each other but can be used in arithmetic operations together.📃 Motivating Example
TypeScript’s structural typing is powerful but can cause issues when types that are structurally identical represent different semantic concepts, like
UserId
andProductId
both beingnumber
. Developers currently use intersection types (e.g.,number & { __brand: 'UserId' }
) to enforce distinction, but this approach is cumbersome and leads to confusing error messages. Thebrand
keyword provides a clean, native solution that enhances type safety and developer experience. Here’s how it improves the language:This feature eliminates the need for hacks, provides clear error messages, and aligns with TypeScript’s structural typing philosophy.
💻 Use Cases
What do you want to use this for?
To safely distinguish between different kinds of identifiers, measurements, or other primitive-based types that should not be interchangeable, such as
UserId
vs.ProductId
, orKilometers
vs.Miles
.What shortcomings exist with current approaches?
What workarounds are you using in the meantime?
type UserId = number & { __brand: 'UserId' };
to achieve type distinction.The
brand
keyword addresses these issues by offering a straightforward, language-supported way to define and enforce branded types, improving both safety and usability in TypeScript projects.The text was updated successfully, but these errors were encountered: