4 ms·
Good question! It wasn't easy to get the question mark on the left-hand side, but it is possible. Here's the Zod equivalent: const C = z.object({ foo: z
by colinmcd 7y ago
Good question! It wasn't easy to get the question mark on the left-hand side, but it is possible.
Here's the Zod equivalent:
const C = z.object({
foo: z.string(),
bar: z.number().optional(),
});
type C = t.TypeOf<typeof C>;
/* {
foo: string;
bar?: number | undefined
} */
And here's the code that pulls this off:
type OptionalKeys<T extends z.ZodRawShape> = {
[k in keyof T]: undefined extends T[k]['_type'] ? k : never;
}[keyof T];
type RequiredKeys<T extends z.ZodRawShape> = Exclude<keyof T, OptionalKeys<T>>;
type ObjectType<T extends z.ZodRawShape> = {
[k in OptionalKeys<T>]?: T[k]['_type'];
} &
{ [k in RequiredKeys<T>]: T[k]['_type'] };
export class ZodObject<T extends z.ZodRawShape> extends z.ZodType<
ObjectType<T>, // { [k in keyof T]: T[k]['_type'] },
ZodObjectDef<T>
>{
// ...
}
- eyelidlessness 7y agoLooks pretty similar to how I did it with io-ts! I'm pretty surprised that they don't support it by now.
- Ezku 7y agoThanks for the reply. So, careful application of mapped types and removing the ability to type a property as `foo: bar | undefined`. I understand this is desirable a lot of times especially if you can’t affect the format of what’s being parsed, but I’m not sure this is unambiguously better. FWIW it’s made my life easier to say the keys will always be there, but the values are possibly undefined. Less room for ambiguous interpretation.