profile
viewpoint
Colin McDonnell vriad Bagel Health Cupertino, CA https://vriad.com I have come here to chew bubblegum and write code. And _InsufficientBubblegumException_. | Creator of Zod | Founder of Bagel Health | MIT 2016

vriad/devii 203

A developer blog starter for 2020 (Next.js + React + TypeScript + Markdown + syntax highlighting)

vriad/bye-react 125

Command-line tool to migrate React to Preact

vriad/next-firebase-ssr 32

An Next.js example repo for building authenticated pages with Firebase Authentication, cookies, and getServerSideProps

PopcornNotify/popcorn-notify 5

Node.js module for PopcornNotify

vriad/DougNotes 3

Graphical dynamic knowledge repository platform

vriad/awesome-nextjs 1

:notebook_with_decorative_cover: :books: A curated list of awesome resources : books, videos, articles about using Next.js (A minimalistic framework for universal server-rendered React applications)

vriad/awesome-typescript 1

A collection of awesome TypeScript resources for client-side and server-side development. Write your awesome JavaScript in TypeScript

vriad/gwen 1

Utility-first CSS-in-JS styling library for maniacs

vriad/npm-ts-starter 1

A project template for TypeScript npm packages

issue closedvriad/zod

How to get all the defaults from schema?

Something like

const schema = z.object({
  name: z.string().default("A"),
});


schema.getDefaults()

// returns:
{ name: 'A' }

closed time in 3 hours

xiaoyu-tamu

issue commentvriad/zod

How to get all the defaults from schema?

The best way is just to parse an empty object. But this will fail unless you've defined a default on every child in the object:

schema.parse({}) // => { name: 'A' }
xiaoyu-tamu

comment created time in 3 hours

issue commentvriad/zod

Zod2: Nested transform don't work

I agree this is quite unintuitive. I'm also not sure if this is fixable.

The problem seems to be with your implementation of transformArray. You shouldn't be allowed to implement that function in that way; it's only possible because z.ZodTypeAny is perhaps too permissive and contains lots of anys.

If you "unwrap" the top-level call to transformArray you can see the type error that Zod should have surfaced:

const transformArray = <T extends z.ZodTypeAny>(childSchema: T) => {
  const schema = z.object({
    elements: z.array(childSchema),
  });

  return z.transformer(schema, z.array(childSchema), val => {
    return val.elements;
  });
};

const classSchema = z.object({
  students: transformArray(
    z.object({
      id: z.number(),
    }),
  ),
});

const classesSchema = z.transformer(
  z.object({ elements: z.array(classSchema) }),
  z.array(classSchema),
  val => {
    return val.elements;
  },
);
Argument of type '(val: { elements: { students: { id: number; }[]; }[]; }) => { students: { id: number; }[]; }[]' is not assignable to parameter of type '(arg: { elements: { students: { id: number; }[]; }[]; }) => { students: { elements: { id: number; }[]; }; }[] | Promise<{ students: { elements: { id: number; }[]; }; }[]>'.
  Type '{ students: { id: number; }[]; }[]' is not assignable to type '{ students: { elements: { id: number; }[]; }; }[] | Promise<{ students: { elements: { id: number; }[]; }; }[]>'.
    Type '{ students: { id: number; }[]; }[]' is not assignable to type '{ students: { elements: { id: number; }[]; }; }[]'.
      Type '{ students: { id: number; }[]; }' is not assignable to type '{ students: { elements: { id: number; }[]; }; }'.
        Types of property 'students' are incompatible.
          Property 'elements' is missing in type '{ id: number; }[]' but required in type '{ elements: { id: number; }[]; }'.

This is definitely a major issue with how transformers are currently implemented. I'll keep thinking about this one.

lucaspiller

comment created time in 3 hours

push eventvriad/devii

Jon Winstanley

commit sha 14a325fa51a8213558ddc8c4a60c91db2f962d12

Remove commented code and blank lines

view details

Jon Winstanley

commit sha 3ae1f689ff352ab607abbeb11aab7dab0ec5de91

Code formatting

view details

Jon Winstanley

commit sha 25d3f52cc1322af056d71e42bb1d74db9d6db0a1

Code formatting of inline CSS rules

view details

Jon Winstanley

commit sha 40e6a86f35e46e888e41c176874510896c4cf667

Top heading is now a h1

view details

Jon Winstanley

commit sha 92ed66265854184f4de19a2b24256d3c248fdd81

Code formatting

view details

Jon Winstanley

commit sha 7de3490e6ec02a66884f70ac4da74b728d1147a3

Add space in CSS rule

view details

Jon Winstanley

commit sha b666dff03854bb6179ac54a3d5d720c67f80b82d

Order the blog post and frontmatter points next to each other

view details

Jon Winstanley

commit sha c11d08a2f0438bc0ecf93f52171c55a9cd4b8329

Add items to Readme

view details

Jon Winstanley

commit sha 67439ecd3d855008ff3d376e0bd2e2de27ceabab

Remove unused index

view details

Jon Winstanley

commit sha 0f59bf1c05655cbfb69c2ab89b92320a7c4d2968

Improve readability

view details

Colin McDonnell

commit sha 846f1ee7d249efaca8d096bc8175ad1a3791fa54

changes to homepage

view details

Colin McDonnell

commit sha 8fc3e436f61a85ed058a7f055b97b97b78ca44f8

Fmc

view details

Colin McDonnell

commit sha 9545035cc23578a753d90ca1482c11fba2b01298

Formatting and CSS improvements

view details

push time in 6 hours

PR merged vriad/devii

Clean up of code formatting and removal of commented code

I've tried to standardise the way CSS rules have been formatted and have tidied up a few parts of the code. Hope this helps.

+84 -88

0 comment

16 changed files

jonwinstanley

pr closed time in 6 hours

starteddvargas92495/roam-js-extensions

started time in 2 days

issue commentprisma/prisma

Generating client to custom location with Next.js is broken

I solved this issue for myself by doing a couple things:

First, overriding the node.__dirname Webpack setting inside next.config.js.

// node.config.js

const CopyWebpackPlugin = require('copy-webpack-plugin'); // npm install copy-webpack-plugin
const path = require('path');

module.exports = {
  // stuff here
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {

    // copy binary into the appropriate locations within `.next/serverless`
    config.plugins.push(
      new CopyWebpackPlugin({
        patterns: [
          {

            // the custom location the binary is generated to
            from: path.join(
              __dirname,
              'path/to/binary/query-engine*', // glob pattern that matches all query-engines
            ),

            to: path.join(__dirname, '.next/serverless/pages/api'),
          },
        ],
      }),
    );

    // set to false
    config.node.__dirname = false;
    return config;
  },
};

This solution was first proposed here.

Related issues:

  • https://github.com/prisma/prisma/issues/2303
  • https://github.com/prisma/prisma-client-js/issues/616
  • https://github.com/prisma/prisma/issues/2195
flybayer

comment created time in 4 days

issue commentprisma/prisma-client-js

Query engine binary could not be found

I solved this issue by overriding the node.__dirname Webpack setting inside next.config.js.

// node.config.js

module.exports = {
  // stuff here
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    config.node.__dirname = false;
    return config;
  },
};

This solution was first proposed here.

Related issues:

  • https://github.com/prisma/prisma/issues/2303
  • https://github.com/prisma/prisma-client-js/issues/616
  • https://github.com/prisma/docs/issues/841
iherger

comment created time in 4 days

issue commentvriad/zod

Would you add comparison with $mol_data?

PR welcome 👍

nin-jin

comment created time in 5 days

issue commentvriad/zod

RFC: Mocking

I'm inclined to disagree. This would add maybe a kilobyte to the bundle size max. Plus I consider mocking is a pretty fundamental bit of functionality for a library that is trying to be the single-source of truth for type information.

Pretty sure we could eliminate more than a kilobyte from the bundle by using the removeComments option in tsc...just realized I haven't enabled that 😬

vriad

comment created time in 5 days

issue closedvriad/zod

Using .mock() as a .default() only in testing?

Hey hey,

So we are looking at using a "zod first approach" to developing libraries (DDD?).

As such we have just been looking at a way to quickly mock inputs during develop and testing. One idea we had was to use .default() to produce the test data - but then we realised this didn't make sense as we would then have these defaults in production as well.

It would be great if there were an equivalent .mock() that would return a mock value if no other is received and node env == dev or test (or some other config).

cc @iainkirkpatrick

closed time in 7 days

agentlewis

issue commentvriad/zod

Using .mock() as a .default() only in testing?

The "dynamic default" (e.g. passing a function that returns a default value) is now available in zod@2.0.0-beta.16 👍

const randomDefault = z
    .number()
    .default(() => Math.random())

// returns a new random number every time `parse` is called
randomDefault.parse(undefined);

Zod makes sure the returned value matches the expected type signature:

const randomDefault = z
    .number()
    .default(() => 'qwerty') // TypeError
agentlewis

comment created time in 7 days

push eventvriad/zod

Colin McDonnell

commit sha 17f0e152ec6ceddfbff582fff3897516a0836e72

Added dynamic defaults

view details

push time in 7 days

issue commentvriad/zod

Support for Map and Set

Support for maps just arrived in Beta 15 courtesy of @lo1tuma ✨

lo1tuma

comment created time in 7 days

pull request commentvriad/zod

Add z.map() to support Map objects

Merged in zod@2.0.0-beta.15! Thanks @lo1tuma for a fantastic PR here. Sorry for the delay on this.

lo1tuma

comment created time in 7 days

PR merged vriad/zod

Add z.map() to support Map objects

Refs: #172

+192 -18

0 comment

10 changed files

lo1tuma

pr closed time in 7 days

push eventvriad/zod

Mathias Schreck

commit sha 9c94f5a3bb1a442b9cf78bc31c9b7f10de17ace6

Add z.map() to support Map objects

view details

Colin McDonnell

commit sha 1ccfcdfe2beaf4b65db9318b870568b116d79a1a

Merge branch 'support-map' of git://github.com/lo1tuma/zod into lo1tuma-support-map

view details

Colin McDonnell

commit sha 6599ba53ad28766d58adaf9a8eb64effbfd3dd42

Improved implementation of Map. Major improvements on PseudoPromise all and object.

view details

Colin McDonnell

commit sha 40741191c0ac7094ce58672e88419bfa3aaeb357

Merge branch 'lo1tuma-support-map' into v2

view details

Colin McDonnell

commit sha d30a9f4bb2a2b29957beaca9198861ec24d2d78d

Fixed switcher bug

view details

push time in 7 days

issue commentvriad/zod

Using .mock() as a .default() only in testing?

I just opened an RFC for mocking here: https://github.com/vriad/zod/issues/197

Feel free to comment 🤙

agentlewis

comment created time in 7 days

issue openedvriad/zod

RFC: Mocking

I'm open to a PR for a .mock method that lets you generate mock data for your schemas.

Proposal

A .mock method on the base class.

z.string().mock(); // => "AkvoFxGfoHFhdfKF" (random string)
z.number().mock(); // => 18916.19016 (random number)

This method could accept some parameters that let you overriding the default mocking functions for each data type (e.g. strings, numbers, tuples, etc).

z.string().mock({
  stringMocker: ()=>['hello', 'goodbye'][Math.round(Math.random())]
});
// => randomly chooses "asdf" or "qwer"

There would also need to be a way to override the mocking function for a particular schema instance (probably a .mocker() or .setMocker() method on the base class).

z.string()
  .refine(val=>val === val.toLowerCase())
  .mocker(()=>{
    return randomString().toLowerCase();
  })
  .mock(); // => "akvofxgfohfhdfkf"

Issues

A few issues comes to mind:

  • Refinements: Zod has no way of generating a value that satisfies a given refinement. There would also need to be a way to override the mocking function for a particular schema instance (probably a .mocker() or .setMocker() method on the base class).
  • Unions: which union "option" should be used to generate the value? Perhaps a randomly chosen one? Should the mocked value for an optional value be undefined 50% of the time?
  • Transformers: should Zod mock a value for the input or the output type? Not a huge issue, this can just be an option/flag in the .mock method.

created time in 7 days

issue commentvriad/zod

Using .mock() as a .default() only in testing

I don't want to modify the behavior of .default in different environments. There are too many different ways of determining a dev/prod environment, and I don't want to be opinionated on that front.

But I'm open to a PR for a separate .mock method.

My preferred approach to this would be a .mock method on the base class. This method could accept some parameters that let you overriding the default mocking functions for each data type (e.g. strings, numbers, tuples, etc).

There would also need to be a way to override the mocking function for a particular schema instance (probably a .mocker() or .setMocker() method on the base class). This lets you mock refinement types like emails or UUIDs.

One complexity that comes to mind:

  • Refinements: Zod has no way of generating a value that satisfies a given refinement. There would also need to be a way to override the mocking function for a particular schema instance (probably a .mocker() or .setMocker() method on the base class).
  • Unions: which union "option" should be used to generate the value? Perhaps a randomly chosen one? Should the mocked value for an optional value be undefined 50% of the time?
  • Transformers: should Zod mock a value for the input or the output type? Not a huge issue, this can just be an option/flag in the .mock method.
agentlewis

comment created time in 7 days

issue closedvriad/zod

Not getting infer in TS types

image

I am on the beta version of Zod and I'm facing this error from TypeScript.

This is my tsconfig.json

{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */
    /* Basic Options */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "ES2018" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
    "lib": [
      "ESNext"
    ] /* Specify library files to be included in the compilation. */,
    // "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    "sourceMap": true /* Generates corresponding '.map' file. */,
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    "outDir": "./dist" /* Redirect output structure to the directory. */,
    // "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
    // "composite": true,                     /* Enable project compilation */
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    // "removeComments": true,                /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    "isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */,
    /* Strict Type-Checking Options */
    "strict": true /* Enable all strict type-checking options. */,
    "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
    "strictNullChecks": true /* Enable strict null checks. */,
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */
    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */
    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
    /* Advanced Options */
    "skipLibCheck": true /* Skip type checking of declaration files. */,
    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  },
  "include": [
    "src/**/*"
  ]
}

closed time in 7 days

ryands17

issue commentvriad/zod

Not getting infer in TS types

It should be

type myTypeName = z.infer<typeof myZodSchema>

Then you can define variables like this:

const myVar: myTypeName = ...
ryands17

comment created time in 7 days

issue closedvriad/zod

z.infer not required by default?

image

I'm using Typescript 4.0.3 and zod 1.11.9

closed time in 8 days

ralphilius

issue commentvriad/zod

z.infer not required by default?

This happens when you don't have "strictNullChecks": true in your tsconfig.json.

Screen Shot 2020-10-18 at 8 51 04 PM

ralphilius

comment created time in 8 days

startedhiradary/reoverlay

started time in 8 days

issue commentvriad/zod

Error stack trace should not include Zod internals

Open to a PR for this. TBH I don't know how to do this.

flybayer

comment created time in 11 days

CommitCommentEvent

push eventvriad/zod

Colin McDonnell

commit sha 1bd9af3ede3752266c60c0b806cf3c8e1e9dc771

Fixed pseudopromise cIndex bug

view details

push time in 11 days

issue commentvriad/zod

[Feature Request]: zod2 access to refinementData

I don't like this solution because of this part:

we can simply loop over the zod-fields and generate the meta-data and HTML form

If you're looping over the fields of a Zod object schema to generate your form, you don't have any type information about the metadata available on each one. To use your example:

const userSchema = z.object({
  firstName: z.string()
    .min(5)
    .max(25)
    .nonempty()
    .meta({
      description: ' the users first name',
    }),
  name: z.string()
    .min(5)
    .max(25)
    .nonempty()
    .meta({
      description: 'the users name',
    }),
});

// Component.jsx
{ Object.keys(userSchema.shape).map(key => {
  const fieldSchema = userSchema.shape[key];
  // fieldSchema has virtually no type information inside this loop
}) }

Since you don't have type information there, I personally find this to be an anti-pattern that I don't want to encourage. Which is why I recommend writing a higher-level wrapper that stores your form field metadata like I suggest here: https://github.com/vriad/zod/issues/76#issuecomment-673271898. Better yet, the

There is some redundancy unfortunately. You can eliminate a lot of it by fleshing out the simple ZodForm class I proposed. Below is an example of how that would work:

import * as z from '.';

type MyFormInput<Key extends string = string> = {
  type: 'string' | 'number' | 'checkbox' | 'select';
  key: Key;
  label: string;
  placeholder: string;
  validator?: z.ZodSchema<unknown>;
};

class ZodForm<Inputs extends [...MyFormInput<any>[]] = []> {
  inputs: Inputs;
  constructor(inputs: Inputs) {
    this.inputs = inputs;
  }

  input = <Input extends MyFormInput>(
    input: Input,
  ): ZodForm<[...Inputs, Input]> => {
    return new ZodForm([...this.inputs, input]);
  };

  string = <Input extends Omit<MyFormInput, 'type'>>(
    input: Input,
  ): ZodForm<[...Inputs, MyFormInput<Input['key']>]> => {
    return new ZodForm([
      ...this.inputs,
      { type: 'string', validator: z.string(), ...input },
    ] as any);
  };
}

I have a lot of ideas around typesafe form definition but in the end, the best thing is to define your own TypeScript data structures that store the exact pieces of metadata you like. I would love if you (or anyone) built a form definition library on top of Zod since it's such a common use case. I have lots of ideas about how to build/define forms in a typesafe way. I've also tried to do this I have lots of ideas regarding this @tmtron I think expanding the ZodForm example into a more comprehensive form definition library would be extremely cool, and is the best way to solve your problem.

tmtron

comment created time in 11 days

issue closedvriad/zod

v2 beta: Type 'Shape' does not satisfy the constraint 'ZodRawShape'

When compiling with zod@2.0.0-beta.9 on TypeScript 4.0.3, I get this error:

node_modules/zod/lib/src/helpers/partialUtil.d.ts(11,39): error TS2344: Type 'Shape' does not satisfy the constraint 'ZodRawShape'.
node_modules/zod/lib/src/helpers/partialUtil.d.ts(11,94): error TS2344: Type '{ [k in keyof Shape]: DeepPartial<Shape[k]>; }' does not satisfy the constraint 'ZodRawShape'.
  Type 'DeepPartial<Shape[k]>' is not assignable to type 'ZodTypeAny'.
    Type '{ object: Shape[k] extends ZodObject<infer Shape, infer Params, ZodTypeAny, { [k in keyof addQuestionMarks<{ [k in keyof infer Shape]: infer Shape[k]["_output"]; }>]: addQuestionMarks<...>[k]; }, { [k in keyof addQuestionMarks<...>]: addQuestionMarks<...>[k]; }> ? ZodOptional<...> : never; rest: ReturnType<...>; }[S...' is not assignable to type 'ZodType<any, any, any>'.
      Type '{ object: Shape[k] extends ZodObject<infer Shape, infer Params, ZodTypeAny, { [k in keyof addQuestionMarks<{ [k in keyof infer Shape]: infer Shape[k]["_output"]; }>]: addQuestionMarks<...>[k]; }, { [k in keyof addQuestionMarks<...>]: addQuestionMarks<...>[k]; }> ? ZodOptional<...> : never; rest: ReturnType<...>; }[S...' is not assignable to type 'ZodType<any, any, any>'.
        Type '{ object: Shape[k] extends ZodObject<infer Shape, infer Params, ZodTypeAny, { [k in keyof addQuestionMarks<{ [k in keyof infer Shape]: infer Shape[k]["_output"]; }>]: addQuestionMarks<...>[k]; }, { [k in keyof addQuestionMarks<...>]: addQuestionMarks<...>[k]; }> ? ZodOptional<...> : never; rest: ReturnType<...>; }[S...' is not assignable to type 'ZodType<any, any, any>'.
          Type '{ object: Shape[k] extends ZodObject<infer Shape, infer Params, ZodTypeAny, { [k in keyof addQuestionMarks<{ [k in keyof infer Shape]: infer Shape[k]["_output"]; }>]: addQuestionMarks<...>[k]; }, { [k in keyof addQuestionMarks<...>]: addQuestionMarks<...>[k]; }> ? ZodOptional<...> : never; rest: ReturnType<...>; }[S...' is not assignable to type 'ZodType<any, any, any>'.
            Type '(Shape[k] extends ZodObject<infer Shape, infer Params, ZodTypeAny, { [k in keyof addQuestionMarks<{ [k in keyof infer Shape]: infer Shape[k]["_output"]; }>]: addQuestionMarks<{ [k in keyof infer Shape]: infer Shape[k]["_output"]; }>[k]; }, { [k in keyof addQuestionMarks<...>]: addQuestionMarks<...>[k]; }> ? ZodOptio...' is not assignable to type 'ZodType<any, any, any>'.
              Type 'ReturnType<Shape[k]["optional"]>' is not assignable to type 'ZodType<any, any, any>'.
                Type 'unknown' is not assignable to type 'ZodType<any, any, any>'.
                  Type 'ReturnType<Shape[keyof Shape]["optional"]>' is not assignable to type 'ZodType<any, any, any>'.
                    Type 'unknown' is not assignable to type 'ZodType<any, any, any>'.
                      Type 'ReturnType<Shape[string | number | symbol]["optional"]>' is not assignable to type 'ZodType<any, any, any>'.
                        Type 'unknown' is not assignable to type 'ZodType<any, any, any>'.
                          Type 'ReturnType<Shape[string]["optional"]> | ReturnType<Shape[number]["optional"]> | ReturnType<Shape[symbol]["optional"]>' is not assignable to type 'ZodType<any, any, any>'.
                            Type 'ReturnType<Shape[string]["optional"]>' is not assignable to type 'ZodType<any, any, any>'.
                              Type 'unknown' is not assignable to type 'ZodType<any, any, any>'.
node_modules/zod/lib/src/helpers/partialUtil.d.ts(12,45): error TS2344: Type 'Shape[k]' does not satisfy the constraint 'ZodTypeAny'.
  Type 'Shape[keyof Shape]' is not assignable to type 'ZodType<any, any, any>'.
    Type 'Shape[string] | Shape[number] | Shape[symbol]' is not assignable to type 'ZodType<any, any, any>'.
      Type 'Shape[string]' is not assignable to type 'ZodType<any, any, any>'.
  • zod@1.11.9 compiles fine
  • When looking at node_modules/zod/lib/src/helpers/partialUtil.d.ts(11,39) I see red squiggles in VS Code. I suspect it could be a type error in the library.

My tsconfig.json:

{
  "compilerOptions": {
    "module": "CommonJS",
    "target": "ES2019",
    "strict": true,
    "outDir": "dist",
    "esModuleInterop": true
  },
  "include": ["src"]
}

closed time in 11 days

MajorBreakfast

issue commentvriad/zod

v2 beta: Type 'Shape' does not satisfy the constraint 'ZodRawShape'

Sorry for the delay on getting this fixed, I was moving across the US...long drive.

The new issue was unrelated (typo by me!) and is also resolved.

MajorBreakfast

comment created time in 11 days

issue closedvriad/zod

v2.0.0-beta.12: Cannot find module <...>/node_modules/zod/[]]./lib/src/index.js'.

After upgrading to v2.0.0-beta.12 I started getting the following error:

Cannot find module <...>/node_modules/zod/[]]./lib/src/index.js'.

Caused by this line: https://github.com/vriad/zod/blob/v2/package.json#L5

It seems that the main field in the package.json file was very recently changed from:

"main": "./lib/src/index.js",

to

"main": "[]]./lib/src/index.js",

closed time in 11 days

marlonbernardes

issue commentvriad/zod

v2.0.0-beta.12: Cannot find module <...>/node_modules/zod/[]]./lib/src/index.js'.

Fixed by #193 - it was an accident, my bad!

marlonbernardes

comment created time in 11 days

pull request commentvriad/zod

fix: update path to main file in package.json. Fixes #192

Whoops...weird. Thanks for the PR! Merged, fixed, and published to NPM.

marlonbernardes

comment created time in 11 days

push eventvriad/zod

Marlon Bernardes

commit sha f709a30313576a0a5d079c34bdc3635b6438aa75

fix: update path to main file in package.json. Fixes #192

view details

Colin McDonnell

commit sha 1f79eb5e609e75b311ce7e2dbe429b8ae6f42ae8

Merge pull request #193 from marlonbernardes/fix/package-json-main-file fix: update path to main file in package.json. Fixes #192

view details

push time in 11 days

PR merged vriad/zod

fix: update path to main file in package.json. Fixes #192

@vriad Not sure why this was changed in first place - perhaps it was an accident, as I'm unfamiliar with this syntax.

+1 -1

1 comment

1 changed file

marlonbernardes

pr closed time in 11 days

issue closedvriad/zod

[Feature Request]: Ability to provide a message to types

I am currently using Blitz.js which uses zod for validation on the server and on the client. Everything works perfectly exept one small thing. When I want to customize the error message "Required" that is thrown by z.string() or other similar functions, there is not a good way to to it. With min() i can just provide the message as a prop, for z.string() I either have to provide a custom ZodErrorMap or avoid using zod for this. Would it be possible to change the string method to exept a message prop like this?

z.string({message: "Email is a required field."})

or

z.string("Email is a required field.")

closed time in 11 days

enricoschaaf

issue commentvriad/zod

[Feature Request]: Ability to provide a message to types

This is a duplicate of #97, so I'm gonna close for now. This is on the roadmap.

enricoschaaf

comment created time in 11 days

PR closed vriad/zod

fix(parser): incorrect promise error handling

Currently, if you have a Zod Function Schema and you say it returns a Promise value then Zod will create a new Promise wrapping the returned Promise. When the wrapped Promise resolves it will validate it with the Promise type parser and if it doesn't validate it will reject the new Promise or resolve it if the parsing succeeds.

However, wrapping a Promise into a new Promise breaks catching the Promise rejection further up the stack as the Promise that generates the error is not the Promise anything is attaching .catch too or wrapping in a try {} catch {} block.

Instead of wrapping the Promise we can simply just add a new .then chain which performs the validation. If it throws it will automatically reject the Promise and it ensures that the correct Promise is having error handling added to it further up the stack.

I created this in the web-editor and haven't tested any other scenario, but I have applied the same patch to my local copy of Zod and it now correctly handles rejected promises.

<!-- Reviewable:start -->

This change is <img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/> <!-- Reviewable:end -->

+1 -9

1 comment

1 changed file

UberMouse

pr closed time in 11 days

issue closedvriad/zod

Failed async refinement causes other `issues` to not be returned

When using the new safeParseAsync an async validation failure causes the issues array to only contain the async failure, the other errors are not included in the returned value. Is this expected? The failing test is posted below.

import * as z from 'zod'

test('testing zod', () => {
  expect.assertions(2)
  const base = z.object({
    hello: z.string(),
    foo: z.number()
      .refine(async (data) => {
        return false
      }, {message: "invalid"})
  })
  const result = base.safeParseAsync({hello: 3, foo: 3})

  return result.then(r => {
    expect(r.success).toBe(false)
    if (r.success === false) 
      expect(r.error.issues.length).toBe(2) // <--- `issues` has length of 1 here
  });
});

closed time in 11 days

ntilwalli

issue commentvriad/zod

Failed async refinement causes other `issues` to not be returned

Fixed in zod@2.0.0-beta.12 thanks to some great work by @ntilwalli. Thanks Nikhil!!!

ntilwalli

comment created time in 11 days

issue closedvriad/zod

z.string() satisfied with empty string in ^2.0.0-beta.9

^2.0.0-beta.9

Tested with z.string().parse("") as well.

I don't suppose this is the expected behaviour?

closed time in 11 days

johnnypea

issue commentvriad/zod

z.string() satisfied with empty string in ^2.0.0-beta.9

Thanks @lazharichir !

@johnnypea Oops guess I forgot to document this. Thanks for pointing that out!

johnnypea

comment created time in 11 days

push eventvriad/zod

Colin McDonnell

commit sha 930ba29c3cb846e9bb70849f253fa7c591430937

added string.nonempty to readme

view details

push time in 11 days

issue closedvriad/zod

Missing type for discriminated union result of safeParse

Maybe I am doing something incorrectly here.

If I have an array of results from safeParse, and I want to filter on the successful ones and then use the data from each, I need a type to pass to the Array.filter function. Zod does not export a type like this, because the appropriate type is only defined inline: https://github.com/vriad/zod/blob/d1ae8e3538167a41e13ab6cfc2466ef3ca69e63a/src/types/base.ts#L69

I defined a type that takes the typeof of a schema as input, and can then be passed to .filter to allow this behavior.

The type is:

type ZodSafeParseSuccess<T extends zod.ZodSchema<T['_input']>> = { success: true; data: zod.infer<T> };

And assuming parseResult is the output of calling safeParse on an input (say objects retrieved from a database or sent by a client), here is example usage:

  [parseResult]
    .filter(
      (result): result is ZodSafeParseSuccess<typeof someSchema> => result.success === true,
    )
    .map((result) => result.data);

Here, in the .map tsc will know that data exists and infer its type correctly based on the schema.

An appropriate ZodSafeParseError type could easily be derived similarly.

Looking forward to feedback - was there an easier way to do this, or should this be closed as a reference for how to fix, or should I open a PR and add this type definition into Zod?

closed time in 11 days

instantepiphany

issue commentvriad/zod

Missing type for discriminated union result of safeParse

I see what you're trying to do. I recommend using TypeScript utilities to "extract" the type.

const schema = await z.object({ name: z.string() }).catchall(z.number());
type schemaResult = ReturnType<typeof schema['safeParse']>;

I find this cleaner than exporting a bunch of utilities like ZodSafeParseSuccess. This is a fairly advanced/niche use case so I don't think I'll add this to the docs - they're cluttered enough already 👍

instantepiphany

comment created time in 11 days

issue commentvriad/zod

v2 beta: Type 'Shape' does not satisfy the constraint 'ZodRawShape'

A fix has been merged in zod@2.0.0-beta.11. I had trouble reproducing the original issue so if someone could confirm that the build is working, that would be great. Leaving open until then.

MajorBreakfast

comment created time in 11 days

issue closedvriad/zod

catchall doesn't work in 2.0.0-beta.9

The example for .catchall in the readme doesn't return the correct result:

> z.object({name: z.string()}).catchall(z.number()).parse({name: "Foo", validExtraKey: 61})
{ name: 'Foo' }

It should have returned:

{name: 'Foo', validExtraKey: 61}

closed time in 11 days

yunyu

issue commentvriad/zod

catchall doesn't work in 2.0.0-beta.9

Thanks for pointing this out! Very dumb bug indeed. Fixed in zod@2.0.0-beta.12.

yunyu

comment created time in 11 days

push eventvriad/zod

Colin McDonnell

commit sha 4453e84b494ee2b5b4d432ff375554cc1f44f3dd

Added catchall tests

view details

push time in 11 days

push eventvriad/zod

Colin McDonnell

commit sha ee2ae29863b97f190ff7141c9edfc9f7f6ce57ad

Fixed catchall bug

view details

Colin McDonnell

commit sha 9216f52f9ff43b7b9885bf63c97c0b104bad6a49

Closes #184

view details

push time in 11 days

push eventvriad/zod

Colin McDonnell

commit sha dc75c69005c9659507aae47b8b33ba427e151627

cleared playground

view details

push time in 11 days

PR closed vriad/zod

feat: add the current path as a refinement `check` parameter

This is a follow-up PR to (#187). It's not intended for merge, but just to ask the question, what is the proper way to integrate the path into a custom refinement error message? I've made a PR which injects the params.path from the parser into the refinement check args. Is there a better way? For example if I want to throw a ZodError in my custom refinement with the code of ZodIssueCode.invalid_string it requires the path to be set but in the current signature the refinement validation function doesn't have access to the path that is currently being validated. This PR does the work of passing that information down from the parser.

This PR also includes a change which swaps out parallel custom refinements validations (Promise.all) for a serial approach so failed earlier validations will not cause later validations to be run. This is useful, for example, when mixing sync and async validations. When a earlier-in-the-queue sync validation fails, a more costly async validations should not be run.

+312 -89

1 comment

9 changed files

ntilwalli

pr closed time in 11 days

pull request commentvriad/zod

feat: add the current path as a refinement `check` parameter

I added this in zod@2.0.0-beta.10 using a similar approach. Here's a demonstration of how to achieve this using the more advanced .refinement method (which is slightly more advanced than .refine)

const foo = z.string().refinement(
  _val => false,
  (_, ctx) => {
    return {
      code: ZodIssueCode.custom,
      message: `bad path: ${ctx.path.join('.')}`,
    };
  },
);

const data = z.object({ foo });

const t1 = await data.spa({ foo: 'asdf' });
console.log(t1);

If you want to use the path in your validation logic, you can use the even more powerful ._refinement method:

const noNested = z.string()._refinement((_val, ctx) => {
  if (ctx.path.length > 0) {
    ctx.addIssue({
      code: ZodIssueCode.custom,
      message: `schema cannot be nested. path: ${ctx.path.join('.')}`,
    });
  }
});

const data = z.object({
  foo: noNested,
});

// passes
noNested.parse('asdf');

// fails
data.parse({ foo: 'asdf' });
ntilwalli

comment created time in 11 days

push eventvriad/zod

Colin McDonnell

commit sha 982a898d85e30da3ed4a6678477207cb62cfb671

2.0.0-beta.9

view details

Tommaso Nolli

commit sha e5d43dee21eb8f07d38b098a44c21da18443ff71

Possible fix for #180

view details

Colin McDonnell

commit sha bbc3672c2a509b7f68391e1a2443b709275d168f

Fixed explicit undefined values for optional keys. Fixes #161

view details

Marlon Bernardes

commit sha bf3487b3b266bd06cdd1f7829520a0622000a52c

Use .default() value only when schema is null or undefined

view details

Marlon Bernardes

commit sha a801d91e1835c3ab0eeb0be5282a699abafea805

Update documentation with more details about new .default() behaviour

view details

Colin McDonnell

commit sha 9bc7c9f4756816370cc684ced7124cf80819b742

Fixes falsy default value issue

view details

Nikhil Tilwalli

commit sha beef4e53ec4a9971f11f467b80c10fd3062e7461

Add PseudoPromise catch for use in ZodType.object

view details

Nikhil Tilwalli

commit sha a8558a2b21f23ac1fd7ed1ae66a5b2b4b073ee20

Add error accumulation for PseudoPromise.object method

view details

Nikhil Tilwalli

commit sha 18c96fd9a741eddbba9dfbffaeb238b322524203

Evaluate async refinement validations serially

view details

Colin McDonnell

commit sha b1826459f240b4ffbdd79ff62aa699bb8b0875c4

Merge branch 'feature/issue-180' of git://github.com/tnolli/zod into tnolli-feature/issue-180

view details

Colin McDonnell

commit sha 47ed87da1099e8938dca797beac57891cde9f7e3

Fixes #180

view details

Colin McDonnell

commit sha 01972b581e103d0169053493980b8d9b49bd4a83

Merge branch 'tnolli-feature/issue-180' into v2

view details

Colin McDonnell

commit sha fd151ec384ab7422cf58596ae50f8eaba22f5587

Merge branch 'pseudocatch' of git://github.com/ntilwalli/zod into ntilwalli-pseudocatch

view details

Colin McDonnell

commit sha 32748735fc12c58b9c8d72ee80a58f756eb12fb3

merged

view details

Colin McDonnell

commit sha 46474e03bcad405ea31a61a9cef28ba26b78943d

merged

view details

Colin McDonnell

commit sha ebe15c6b187b5accbca1e942f455d49c4a86da2d

Implemented runAsyncValidationsInSeries

view details

Colin McDonnell

commit sha 31a8544d42e4f30aafd36a48d457c5cbf0018b6b

Augmentations to pseudopromise

view details

Colin McDonnell

commit sha 894ce002500813bba6638b7aaf8eeeeac3f75e38

Added path to refinement context

view details

Colin McDonnell

commit sha 9c4d3649175f9c031ae8ac00ceac81fca8e44e4c

Merge branch 'ntilwalli-pseudocatch' into v2

view details

Colin McDonnell

commit sha f50fb3fca9035ec34733d891b7d7afa3cbf8998e

FMC and added refinement path test

view details

push time in 11 days

PR merged vriad/zod

Possible fix for #180

This is a possible fix for #180

+5 -4

0 comment

2 changed files

tnolli

pr closed time in 11 days

PR merged vriad/zod

fix: add PseudoPromise catch for use in ZodType.object validation

This PR fixes the async multi-error accumulation bug (#179) by adding a catch method to the PseudoPromise class and using it in while parsing object schemas.

+300 -77

2 comments

9 changed files

ntilwalli

pr closed time in 11 days

pull request commentvriad/zod

fix(parser): incorrect promise error handling

I believe this is fixed in Zod 2. Give it a shot with yarn add zod@beta and let me know if you're getting the expected behavior.

UberMouse

comment created time in 11 days

Pull request review commentvriad/zod

fix: add PseudoPromise catch for use in ZodType.object validation

 export const ZodParser = (schema: z.ZodType<any>) => (   } else {     // if (params.async == true) {     const checker = async () => {-      const resolvedValue = await PROMISE.getValueAsync();--      await Promise.all(-        customChecks.map(async check => {-          await check.check(resolvedValue, checkCtx);-          // if (!checkResult) {-          //   const { check: checkMethod, ...noMethodCheck } = check;-          //   ERROR.addIssue(makeError(noMethodCheck));-          // } else {-          // }-        }),-      );--      if (resolvedValue === INVALID && ERROR.isEmpty) {-        ERROR.addIssue(-          makeError({-            code: ZodIssueCode.custom,-            message: 'Invalid',-          }),-        );+      let resolvedValue = await PROMISE.getValueAsync();+ +      if (resolvedValue !== INVALID) {+        let someError: boolean = false;

Sure I can implement this. How does runAsyncValidationsInSeries sound as a parameter name?

ntilwalli

comment created time in 11 days

PullRequestReviewEvent

pull request commentvriad/zod

fix: add PseudoPromise catch for use in ZodType.object validation

WOW this is some great work. I started trying to fix #179 before I saw this PR and I arrived at the exact same solution. Wonderful! I've already merged this locally and made some some stylistic changes.

I left one comment regarding the someError short-circuiting logic. I'm switching back to a Promise.all approach that runs all the custom checks in parallel and getting rid of the short-circuit. Unless you had a compelling reason for doing it that way?

ntilwalli

comment created time in 12 days

Pull request review commentvriad/zod

fix: add PseudoPromise catch for use in ZodType.object validation

 export const ZodParser = (schema: z.ZodType<any>) => (   } else {     // if (params.async == true) {     const checker = async () => {-      const resolvedValue = await PROMISE.getValueAsync();--      await Promise.all(-        customChecks.map(async check => {-          await check.check(resolvedValue, checkCtx);-          // if (!checkResult) {-          //   const { check: checkMethod, ...noMethodCheck } = check;-          //   ERROR.addIssue(makeError(noMethodCheck));-          // } else {-          // }-        }),-      );--      if (resolvedValue === INVALID && ERROR.isEmpty) {-        ERROR.addIssue(-          makeError({-            code: ZodIssueCode.custom,-            message: 'Invalid',-          }),-        );+      let resolvedValue = await PROMISE.getValueAsync();+ +      if (resolvedValue !== INVALID) {+        let someError: boolean = false;

I don't like that the custom checks short-circuit once an error is encountered. In general Zod tries to surface as many errors as possible upfront, instead of doling them out one by one. Is there some other reason you implemented it this way?

ntilwalli

comment created time in 12 days

PullRequestReviewEvent

issue commentvriad/zod

Support for date, time and date-time format strings

RFC for datetime methods

The hard problem here is naming the methods such that the validation behavior is clear to everyone. I'm opposed to adding a method called .datetime() since different people will have different ideas of what should be valid. I don't like AJV's datetime regex since it allows timezone offsets, which should almost never ever be used imo.

Here is a set of method names I'd be happy with:

  • z.string().date()2020-10-14
  • z.string().time()T18:45:12.123 (T is optional)
  • z.string().utc()2020-10-14T17:42:29Z (no offsets allowed)
  • z.string().iso8601()2020-10-14T17:42:29+00:00 (offset allowed)

The longer method name iso8601 makes the validation rule explicit. The documentation will clearly indicate that using UTC date strings is a best practice and will encourage usage of .utc() over .iso8601().

Milliseconds will be supported but not required in all cases.

maneetgoyal

comment created time in 13 days

issue closedvriad/zod

Ability to require one or another field, or require one field if another is provided

I read through the readme and nothing popped out as supporting this functionality, apologies if I missed something.

The Joi library contains the .with() and .xor() methods which allows you to define whether or not fields are required based on whether or not another field exists. This would be helpful in a case where I want to allow a user to signup with either an email or phoneNumber field, or a password or googleAuthToken, or that both password and repeatPassword exist (and match also?)

You can see how this works in the example in their documention: https://joi.dev/api/?v=17.2.1#example

closed time in 13 days

ablankenship10

issue commentvriad/zod

Ability to require one or another field, or require one field if another is provided

I think Yup's .with approach is interesting but too hard to reason about. I recommend implementing all of these things with custom refinements. The password/confirmPassword approach is specifically addressed here: https://github.com/vriad/zod#custom-validation

@JVictorV Your issue is a little different, see the answer there by @pkerschbaum

ablankenship10

comment created time in 13 days

issue closedvriad/zod

How to relate two object fields?

What is the best way to relate two objects fields in a schema?

Ex:

enum AnimalType {
  Cow,
  Cat,
}

const cowSchema = z.object({
  moo: z.string(),
});

const catSchema = z.object({
  meow: z.string(),
});

const animalSchema = z.object({
  animalType: z.nativeEnum(AnimalType),
  animalData: z.union([cowSchema, catSchema]),
});

I want to parse the object in a way that if the user sets the animalType to Cat, zod will parse animalData using the catSchema. Is it possible to do this without using the refine mehtod?

closed time in 13 days

JVictorV

issue closedvriad/zod

Type 'ZodTransformer<ZodAny, ZodBoolean>' is not assignable to type 'ZodTypeAny'

Is this error meant to be correct? If so I feel like I just missed something fundamental in how to use transforms.

I am using the transforms I created in pip-types, though in the new project I updated zod to "zod": "^2.0.0-beta.9" and can compile and run the tests.

The code:

export const surveyRecordTransform = z.object({
  name: z.string(),
  archive: zToBoolean,
  ... (100 more such lines)
})

I would then use this:

const typedSurveyRecord = surveyRecord.parse(data)

And i get this error (from VSCode type checking)

(property) Archive: ZodTransformer<ZodAny, ZodBoolean>
Type 'ZodTransformer<ZodAny, ZodBoolean>' is not assignable to type 'ZodTypeAny'.

<details> <summary>Rest of error :)</summary>

  Types of property 'parse' are incompatible.
    Type '(x: unknown, params?: ParseParams) => boolean' is not assignable to type '(x: unknown, params?: ParseParams) => any'.
      Types of parameters 'params' and 'params' are incompatible.
        Type 'import("...node_modules/zod/lib/src/parser").ParseParams' is not assignable to type 'import("...node_modules/zod/lib/src/parser").ParseParams'.
          Types of property 'seen' are incompatible.
            Type '{ schema: any; objects: { data: any; error?: any; times: number; }[]; }[]' is not assignable to type '{ schema: ZodType<any, ZodTypeDef, any>; objects: { input: any; error?: ZodError; output: any; }[]; }[]'.
              Type '{ schema: any; objects: { data: any; error?: any; times: number; }[]; }' is not assignable to type '{ schema: ZodType<any, ZodTypeDef, any>; objects: { input: any; error?: ZodError; output: any; }[]; }'.
                Types of property 'objects' are incompatible.
                  Type '{ data: any; error?: any; times: number; }[]' is not assignable to type '{ input: any; error?: ZodError; output: any; }[]'.
                    Type '{ data: any; error?: any; times: number; }' is missing the following properties from type '{ input: any; error?: ZodError; output: any; }': input, outputts(2322)
base.d.ts(29, 5): The expected type comes from this index signature.

</details>

I do realise that I am trying to compose my transform within another Zod object and thinking about this now I realise this may not have been how I am meant to use it.

ie make a bunch of coercion transforms and then use these in Zod Objects to then use on incoming Api data to both map and coerce the types and provide static typing for development... AND very LOUD errors should the coercion fail. #my-little-dream

closed time in a month

agentlewis

issue closedvriad/zod

[Request] Create schema from JSON

I’ve been using YUP which can’t do that and recently saw zod. Just wondering if this is on the table? A use case is a dynamically made schema by my users. Something like zod.importJSON(jsonOBJ)

closed time in a month

cybervaldez

issue commentvriad/zod

[Request] Create schema from JSON

@tonyxiao @cybervaldez @lazharichir This is possible but out of scope for Zod core, in my opinion. I don't want to be responsible for maintaining a bunch of "generate X from Zod" or "generate X from Zod" utilities. Those are best implemented as separate tooling.

Frankly I think generating Zod schemas from JSON schema is a bit of an antipattern and you should just use a JSON-schema validation library in that case. The point of Zod is the type inference, and that's not possible with a JSON import.

If anyone want to take a stab at implementing a "Zod to JSON schema" generator I recommend looking at the parser (src/parser.ts) as a starting point. It's just a recursive function containing a giant switch statement for all the possible subclasses of ZodType. You'll also need to do some basic cycle detection to avoid infinite loops for recursive schemas.

cybervaldez

comment created time in a month

issue closedvriad/zod

[Request] Generate JSON schema out of a zod object

@tonyxiao that's exactly what I am looking for because basically:

  • all my backend services use fastify (rest framework like Express)
  • each route has a JSON Validator built-in
  • each backend service exposes its OpenAPI Spec thanks to these json schemas

So basically, I am looking at a Zod to JSON Schema helper to avoid having to double specify each type. Let me know if you find anything!

Originally posted by @lazharichir in https://github.com/vriad/zod/issues/75#issuecomment-694865003

closed time in a month

cybervaldez

issue commentvriad/zod

[Request] Generate JSON schema out of a zod object

This is possible but out of scope for Zod core, in my opinion. I don't want to be responsible for maintaining a bunch of "generate X from Zod" utilities. If you want to implement this I recommend looking at the parser (src/parser.ts) as a starting point. It's really just a recursive function containing a giant switch statement for all the possible subclasses of ZodType. In Zod 2 all schemas also have utility functions isOptional and isNullable which may help with this.

cybervaldez

comment created time in a month

issue commentvriad/zod

Type 'ZodTransformer<ZodAny, ZodBoolean>' is not assignable to type 'ZodTypeAny'

Looks like you're trying to mix-and-match schemas from Zod 1 (in pip-types) and Zod 2 (in your application code), which is causing the error. You'll have to upgrade pip-types to Zod 2 as well for compatibility.

agentlewis

comment created time in a month

issue commentvriad/zod

Generate an ESM bundle

Sure I'm down - looking forward to the PR 🤙

hmaurer

comment created time in a month

issue closedvriad/zod

In V2 how to get `parseAsync` to collect errors for all fields?

Firstly, thanks for this great lib! I'm wondering how to collect errors for all fields in the new parseAsync method? It seems to stop collecting after the first error.

import * as z from 'zod'

const schema = z.object({
  username: z.string().nonempty(),
  password: z.string().nonempty(),
});

schema.parseAsync({username: '', password: ''})
  .then(() => {})
  .catch(e => {
    if (e.errors.length !== 2) {
      throw 'Expected two errors'
    }
  })

closed time in a month

ntilwalli

issue commentvriad/zod

In V2 how to get `parseAsync` to collect errors for all fields?

The errors property on ZodErrors has been renamed to issues to avoid inconsistency in the usage of the term "error". Previously ZodErrors contained multiple "suberrors" but the property containing was called "errors" and it was the source of a lot of confusion 👍

ntilwalli

comment created time in a month

issue commentvriad/zod

RFC: Transformations (e.g. casting/coercion)

They don't break the "transform chain" but they return a different type than the original instance.

z.string().nullable() is a ZodUnion (or a ZodNullable in Zod 2) z.string().optional() is a ZodUnion (or a ZodOptional in Zod 2) z.string().transform(...) is a ZodTransformer

So you can't access ZodString methods on those.

vriad

comment created time in a month

push eventvriad/zod

Colin McDonnell

commit sha 68d22c47bedc533d598b8cd5b1b862e8b075bb56

Added Bamboo Creative to README

view details

push time in a month

push eventvriad/zod

Colin McDonnell

commit sha b0f2645f8a8a81ce925d57429cee73a590293813

updated readme

view details

push time in a month

push eventvriad/zod

Colin McDonnell

commit sha f2d0d10a5e3d03da27dcb56afd45a60f1094f369

1.11.9

view details

Colin McDonnell

commit sha e55955f29492cb95b039c6c56e7ddfb41b5eeb8d

primitive tests

view details

Colin McDonnell

commit sha 8282dec47a11c6a37083a1e9ffe52cfa5a997966

cleared playground

view details

Colin McDonnell

commit sha 0e6eceba864bd94eec63fdf053720a4e61b6c44e

v2 beta message

view details

Colin McDonnell

commit sha f217a6a4424ccff2c6acc846fa76a4b645ec7b4a

local fix

view details

Colin McDonnell

commit sha 5191f4630a46077bc52942ac2a41c86b60a10018

Merge branch 'master' of github.com:vriad/zod

view details

push time in a month

issue commentvriad/zod

[Discussion] Parsing input that's a superset of the schema type

Thank you! That's always great to hear :)

pjdon

comment created time in a month

issue commentvriad/zod

[Feature Request]: zod2 access to refinementData

Custom error maps are the way to implement logic like this, check out the Error Handling guide for details on that.

tmtron

comment created time in a month

issue closedvriad/zod

Zod 2 beta 5: parse() adds optional fields with 'undefined' as a value

Hi @vriad,

I've upgraded to Zod 2 beta and it works cool.

The first bug I've met now, is that if you send an object without certain optional fields, .parse() adds them with undefined value.

For instance, my schema looks like that (simplified):

export const SNamedEntity = z.object({
  _id: string().refine(validateUUID),
  name: z.string().max(100),
  createdAt: string().refine(validateDateString).optional(),
  updatedAt: string().refine(validateDateString).optional(),
  isActive: boolean().optional(),
});

And the object I send to it has only _id and name. However, when I set a breakpoint after I .parse() this object with the with the above schema, I see that all of the optional fields are present there now:

{ 
  _id: '5f6418f13b179e3da326a1aa',
  name: "John Doe",
  createdAt: undefined,
  updatedAt: undefined,
  isActive: undefined,
}

It freaks out Mongo, it thinks that I'm trying to overwrite its internal createdAt field with undefined and throws me an error.

Interestingly, if I send a valid date in createdAt field, mongo is totally allright with that (it ignores it as it should). Only undefined trips it :)

closed time in a month

grreeenn

issue commentvriad/zod

Zod 2 beta 5: parse() adds optional fields with 'undefined' as a value

@grreeenn @sylvanaar @o-alexandrov this is fixed in zod@2.0.0-beta.9

grreeenn

comment created time in a month

issue commentvriad/zod

Support for Map and Set

PR welcome!

lo1tuma

comment created time in a month

issue commentvriad/zod

.safeParse() and generics

This is possible, let me know if you're still having trouble

grreeenn

comment created time in a month

issue commentvriad/zod

[Question] How do I validate fields after calling .transform?

Thanks again @tmtron !

marlonbernardes

comment created time in a month

pull request commentvriad/zod

Fix for missing values in objects #161

I fixed this issue (using a different approach) in zod@2.0.0-beta.9 👍

sylvanaar

comment created time in a month

issue closedvriad/zod

[Discussion] zod2 - default() condition

The current implementation replaces all falsy values to the default.
I was surprised by this. I expected that only undefined is checked - but maye I'm just biased because I am used to Joi: Joi.default()

There are also cases where we don't want this.

  • a number may have a default of 5, but 0 could also be a valid value
  • and also null can sometimes be a valid value (different from the default)

The options that we have:

  1. default() could have a parameter to decide which to use
  2. we could have 3 different functions: defaultIfFalsy(), defaultIfUndefined(), defaultIfUndefinedOrNull()
  3. or just document in detail how default() function works and force the users of the lib to create custom transformers for the other cases

closed time in a month

tmtron

issue commentvriad/zod

[Discussion] zod2 - default() condition

Fixed in zod@2.0.0-beta.9

Good catch, this was a dumb mistake on my part. The default value should only be applied if the input is undefined.

tmtron

comment created time in a month

pull request commentvriad/zod

Use .default() value only when schema is null or undefined

Merged a version of this. The default value should only be applied if the value is undefined not null. Thanks for doing this! Great PR.

marlonbernardes

comment created time in a month

PR merged vriad/zod

Use .default() value only when schema is null or undefined

Before this change:

const schema = z.object({
  sandbox: z.boolean().default(true)
});

// Good - returns { sandbox: true } - which makes sense as it's not supplied
schema.parse({}); 

// Bad! - returns { sandbox: true } even though I've provided a  value for it.
schema.parse({ sandbox: false }); 

After this change:

const schema = z.object({
  sandbox: z.boolean().default(true)
});

// Good - returns { sandbox: true } - which makes sense as it's not supplied
schema.parse({}); 

// Good - returns { sandbox: false } as a value was supplied to the sandbox property
schema.parse({ sandbox: false }); 

As I'm using the null coalescing operator it means either null or undefined values will cause the default value to be used. We might want to limit this only to undefined values so it matches the same behaviour of joi and yup. Let me know what you think.

Fixes #162

+23 -2

0 comment

3 changed files

marlonbernardes

pr closed time in a month

push eventvriad/zod

Colin McDonnell

commit sha 60b270b0cb677ba71d420fb04cda4334aea45fa1

Implemented object type short circuit

view details

Colin McDonnell

commit sha a855a75783e6ee15ea9ef53d4ba84c1ea2f092e6

2.0.0

view details

Colin McDonnell

commit sha ce6450819e37adb94100bebcd69e36784cc450e5

undid nullable typ short circuit

view details

Colin McDonnell

commit sha 786712de91f517de0ed8f1e4666b18191710369d

2.0.0-beta.6

view details

Colin McDonnell

commit sha 749f1566f9c6ef83c8d39378ccfe71da6bde3bcb

new patch

view details

Marlon Bernardes

commit sha ef1f76a868f9cc8796d2464f15b14cafeca38aec

Use .default() value only when schema is null or undefined

view details

Marlon Bernardes

commit sha ea3c4ea48eba4aeb494ff261fa83b49194066617

Update documentation with more details about new .default() behaviour

view details

Colin McDonnell

commit sha 54f9dda00112b6aeb8985c9026c9291bf1923f3f

updates

view details

Colin McDonnell

commit sha 0170e3c9467dec5ce53d03fc8ee0edeec40bd02e

Fixed explicit undefined values for optional keys. Fixes #161

view details

Colin McDonnell

commit sha c35fe0469aba573da2028bb26bb853419664a619

Merge branch 'fix/default-behaviour' of git://github.com/marlonbernardes/zod into marlonbernardes-fix/default-behaviour

view details

Colin McDonnell

commit sha c87fe1c6fa4406e2fa0b9685f2306811ce884620

Fixes falsy default value issue

view details

Colin McDonnell

commit sha 9c734411dbbfb3d6f8f44421851e7565a1a528ff

Merge branch 'marlonbernardes-fix/default-behaviour' into v2

view details

push time in a month

issue commentvriad/zod

[Discussion] Parsing input that's a superset of the schema type

Hm maybe I misunderstood what you meant but this is not something Zod does:

ignore additional keys, but also mention them in the result.error.errors list

pjdon

comment created time in a month

issue commentvriad/zod

Zod 2 beta 5: parse() adds optional fields with 'undefined' as a value

Okay I replicated this. JSON.stringify() doesn't print keys that correspond to undefined which makes sense. Looking into it.

grreeenn

comment created time in a month

issue commentvriad/zod

RFC: Transformations (e.g. casting/coercion)

Yeah this is an issue with several methods, not just transformers. Notably .optional() and .nullable(). People just have to get used to the fact that chaining order matters 🤷‍♂️

You should either add those checks before the call .transform or in the "destination" type:

z.string().min(5).transform(val => val.trim());

// OR 

z.string().transform(z.string().min(5), val => val.trim());

depending on your use case.

vriad

comment created time in a month

issue commentvriad/zod

Zod 2 beta 5: applying transform() to arrays

Thanks @tmtron!

@grreeenn there probably shouldn't be a difference but I guess it worked out in your case. If anyone else is unhappy with the typing of .nonempty feel free to implement your own validation logic with .refine (which never changes the inferred type).

grreeenn

comment created time in a month

issue closedvriad/zod

Usage in JavaScript

Hi,

Can this library be used with pure JavaScript (no TypeScript)?

I read the documentation and despite the strictNullChecks requirement and types, it doesn't says can't be used with JavaScript.

I made a test here in a mixed JavaScript/TypeScript project without strictNullChecks and it worked.

I was thinking about using the library in a pure JavaScript project, so I would like to see your opinion and recommendations on the matter, possibly mentioning in the docs.

Thanks.

closed time in a month

julianomqs

issue commentvriad/zod

Usage in JavaScript

The strictNullChecks is required for proper static typing, so you're correct that it doesn't affect the runtime execution. There are many closed issues on this repo that will shed some light on the sort of type inference issues you'll experience without strictNullChecks. The biggest issue is that all object properties will be inferred as optional by the type checker.

You can use this in a hybrid/JavaScript project just fine. I'll add this to the readme to avoid more confusion down the road 👍

julianomqs

comment created time in a month

issue closedvriad/zod

[Discussion] Parsing input that's a superset of the schema type

Given a zod schema like

const ZRecord = z.object({
    id: z.number(),
    name: z.string()
});

how can I use ZRecord to extract the schema from a conforming object that has additional fields? E.g.

const result = ZRecord.safeParse({ id: 123, name: "Joe", notes:"enjoys hiking" });

Is there any option that I can pass to the parse methods (e.g. ZRecord.safeParse) that will ignore additional keys, but also mention them in the result.error.errors list? I was hoping that even when result.success was false, result.data would still have the parsed hierarchy. I don't see a way to do this other than iterating through the ZAddEntryParams.shape hierarchy and pulling the relevant attributes from the input into a new "clipped" object before parsing.

It would be valuable to extract the schema from a larger object for something like a web request, to give the API caller a message that they had extra keys in their request.

closed time in a month

pjdon
more