Branded helper
See original GitHub issueInstead of:
type Age = Branded<number, "Age">;
const Age = z
.number()
.min(0)
.max(100)
.refine((a: number): a is Age => true);
Zod can provide a simple helper:
const Age = z
.number()
.min(0)
.max(100)
.brand('Age');
What do you think?
This line:
.refine((a: number): a is Branded<number, "Age"> => true)
to this line:
.brand("Age").
I suppose it’s a tiny change but would improve DX a lot.
Or something like that?
const brand =
<B extends string>(brand: B) =>
<T extends string | number>(a: T): a is Branded<T, typeof brand> =>
true;
.refine(brand("Age"))
OK, this is what I reiterated. Still, I suppose it should be part of the official Zod API.
export type Branded<T extends string | number, B extends string> = T & {
readonly __brand: B;
};
export const branded =
<B extends string, T extends string | number>(
brand: B,
predicate?: Predicate<T>
) =>
(a: T): a is Branded<T, typeof brand> =>
predicate ? predicate(a) : true;
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:8 (1 by maintainers)
Top Results From Across the Web
The Helper Brands
The Cleaner's Helper brand serves the professional cleaning industry, focusing on Carpet Cleaners, Cleaning Companies, and Housekeeping staff. Learn More About ...
Read more >The Helper Brands @ Amazon.com:
Online shopping from a great selection at The Helper Brands Store. ... Handy Helper Tool Belt, Organizer, Carrier for Home, Garden, RV -...
Read more >Helper – Brands – Food we make - General Mills
With more than 60 flavor varieties, the Helper lineup has been a staple for busy family dinners since 1970. It's deliciousness, convenience and...
Read more >Helper - BettyCrocker.com
Betty Crocker Chicken Helper, Fettuccine Alfredo, 8.7 oz. Shop Product ... Hamburger Helper, Bacon Cheeseburger Macaroni Meal, 5.1 oz. Shop Product.
Read more >Brand: Ultimate Helper - Walmart.com
how to draw all the things for kids : drawing helper for kids - the ultimate guide for fast & simple learn (...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
We use branded types a fair bit, so I’m happy to chime in on how they can be used.
With TypeScript’s structural typing, we can’t utilise the type system to ensure zod is being used. Branded types are a way to create a unique type which can only be assigned by parsing with zod. This allows us to use the type system to ensure validation is happening.
As an example;
Defining a schema such as
And we can use the inferred type from our schema within a param for example.
TypeScript’s structural typing means there are no guarantees that input needs to have been parsed by zod first.
Branded types allow us make a type ‘unique’.
If we revisit the save function from above
We’ve now ensured that this case is no longer possible
(Edited to a primitive)
I’ll I’ve been considering a dedicated API for branded types for a long time (#3) but I think the current approaches are more or less equivalent in terms of readability to a dedicated
.brand
API. If you want the result of.parse
to be pretty (e.g.Age
), you have to declare that type separately. At that point you might as well cast or usez.custom
:Open to be convinced though.