Hacker News new | ask | show | jobs
by Ezku 2283 days ago
You mention creating object types with optional keys is cumbersome in io-ts. How is that solved in zod, exactly? What allows you to map `foo: union([bar, undefined])` to `foo?: bar | undefined` (note the question mark on the left hand side)? There’s nothing in the declaration to give away why this wouldn’t yield `foo: bar | undefined` which is what I believe you’d get out of io-ts.

Looks useful - I would have an easier time introducing this than io-ts.

2 comments

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>
  >{ 
    // ...
  }
Thanks 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.

Looks pretty similar to how I did it with io-ts! I'm pretty surprised that they don't support it by now.
With some effort, you can actually mix optionals and required with io-ts as well. If I ever get permission to open source my io-ts wrapper I'd be glad to show you how :)
I look forward to that!

It's definitely possible to wrap `io-ts` to get a better interface, especially if you spend some (or rather, a LOT) of time figuring out the type declarations...