Zod: Generate a basic item using default settings

I have a strong belief that this concept exists, however, my research has not yielded any results. Let's consider a scenario where I have a zod Schema structured like this:

const Person = zod.object({
    name: z.string().default(''),
    age: z.number().nullable();
});

Is it possible to generate a structure similar to the following from the zod Schema?

const InstancePerson = {
    name: '',
    age: null
}

If so, how can this be accomplished through the zod Schema?

Answer №1

While I might be arriving a little late to the gathering, my contribution could potentially benefit someone down the line.

If you wish to expand your `zod` schema further, you can do so by implementing the following modifications:

const Individual = zod.object({
    name: z.string().default(''),
    age: z.number().nullable().default(null)
}).default({}); // In this case, '.default({})' may not be necessary but advisable in nested objects

By executing the following code snippet, you will be able to access the desired outcome:

const NewIndividualInstance = Individual.parse({});

Answer №2

There isn't a straightforward method within the library to achieve this specific task, but by delving into their private fields denoted with _, you can access the desired functionality.

However, it is important to note that this approach comes with certain risks as library developers typically do not assure stability of these private properties. If your code depends on this behavior, caution should be exercised particularly when updating versions.

Setting aside the disclaimer, the potential for something like this exists. The expansion of this concept to encompass more types is left as a challenge for the individual:

import { z } from "zod";

const schema = z.object({
  name: z.string(),
  age: z.number().nullable()
});

const schemaDefaults = <Schema extends z.ZodFirstPartySchemaTypes>(
  schema: Schema
): z.TypeOf<Schema> => {
  switch (schema._def.typeName) {
    case z.ZodFirstPartyTypeKind.ZodDefault:
      return schema._def.defaultValue();
    case z.ZodFirstPartyTypeKind.ZodObject: {
      // Although the switch statement may not have deduced this, the cast seems secure.
      return Object.fromEntries(
        Object.entries(
          (schema as z.SomeZodObject).shape
        ).map(([key, value]) => [key, schemaDefaults(value)])
      );
    }
    case z.ZodFirstPartyTypeKind.ZodString:
      return "";
    case z.ZodFirstPartyTypeKind.ZodNull:
      return null;
    case z.ZodFirstPartyTypeKind.ZodNullable:
      return null;
    // etc
    default:
      throw new Error(`Unsupported type ${schema._type}`);
  }
};

console.log(schemaDefaults(schema));

In this scenario, no defaults have been specified, yet the code still yields the expected output. For instance, if "foo" was designated as the default for name, the result would be

{ name: "foo", age: null }

An alternate, more concise approach could involve exploring one layer deep into the _def of your schema in search of functions like defaultValue to invoke. However, the provided method is deemed superior due to its potential to accommodate all fundamental zod schema types.

To conclude, it is worth mentioning that some zod types pose greater challenges than others. While assigning a default value of 0 to z.number may seem reasonable, handling cases involving z.union or z.intersection presents complex recursive scenarios.

Perhaps creating a dedicated library specifically for this purpose or submitting a feature request to incorporate it into the official API could prove beneficial.

Answer №3

After revisiting this discussion multiple times, I feel it's time to share my perspective:

The issue at hand for me has been about safely creating a new zod object while utilizing the defaults and also requiring non-default inputs.

My dilemma lies in how to effectively use the .parse function which only accepts unknown, making it challenging to discern between required and default values.

If you're facing a similar challenge and seeking something like MyZodObject.createInstance, I may have a straightforward solution.

This solution involves using z.input<typeof MyShape>.

Essentially, this method provides the expected TypeScript type with all necessary keys marked as required while allowing the rest to be filled in by the .default as optional.

For example:

const Model = z.object({
    title: z.string(),
    active: z.boolean().default(false)
})

type ModelOutput = z.infer<typeof Model>
// ^ type ModelOutput = {
//    title: string;
//    active: boolean;
//}

type ModelInput = z.input<typeof Model>
// ^ type ModelInput = {
//    title: string;
//    active?: boolean | undefined; // << DEFAULT
// }

A Simple Method to Instantiate Zod Objects Safely with Default Values


const makeInstantiator =
  <T extends z.ZodType<any>>(model: T) =>
  (input: z.input<T>): z.output<T> => {
    return model.parse(input);
  };

const instantiateModel = makeInstantiator(Model);
// const instantiateModel: (input: {
//   title: string;
//   active?: boolean | undefined;
// }) => {
//   title: string;
//   active: boolean;
// }

Answer №4

Important: After attempting the accepted answer (.parse({})), I encountered issues with using default values that did not meet validation criteria, leading to errors. Additionally, I faced challenges with nested schema fields.


In my exploration, I devised a solution similar to an earlier suggestion. While some typing may be suboptimal (particularly in areas like (fieldSchema._def as ...)), it successfully resolved my linting concerns.

The method outlined below aims to construct a "default" object based on a provided Zod schema, adhering to the following hierarchy and effectively handling nested schema fields (z.object(..)):

  • If a default value is specified for a field (z..default(..)), it is returned immediately
  • If no default value is set & it's a "base" Zod schema field (e.g., z.number(), z.string(), etc.), a corresponding "base" default is retrieved from a designated object (BASE_DEFAULTS)
  • If no default value is set & it's a "transformed" Zod schema field (e.g., z.refine(..), z.coerce(..), etc.), an attempt is made to determine the "inner type" (
    z.ZodTransformationType<z.ZodInnerTypeIsLocatedHere?, ...>
    )
    • This specific scenario hasn't been extensively tested; my approach involves consistently providing defaults to avoid dealing with transformed types

// Code block remains unchanged

Please note that I've primarily utilized this method for generating default values in react-hook-form implementation. The provided BASE_DEFAULTS_FORM differs from standard defaults due to form compatibility requirements (e.g., converting numbers to strings within forms for enhanced usability).

// Code block remains unchanged

Given imperfect typing, certain sections require typecasting. Suggestions for enhancing typing accuracy are welcome!

// Code block remains unchanged

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is causing the inability to successfully copy and paste Vega editor specs locally?

I successfully executed this spec in Vega Editor: { "$schema": "https://vega.github.io/schema/vega/v3.0.json", "width": 1, "height": 1, "padding": "auto", "data": [ { "name": "source", "values": [ {"name": "Moyenne","vo ...

What CSS property prevents a fixed header from overlapping a scrolled element?

After creating a fixed header for my HTML table, I noticed that as I scroll down the page, everything is being overlapped by the fixed header except for one slider (noUiSlider). I am curious to know which CSS property is preventing the header from overlayi ...

Decoding a JSON array containing multiple JSON objects into an ArrayList of org.json.JSONObject instances using Gson

I have a JSON string that looks like this: { "r": [ { "pic": "1.jpg", "name": "Name1" }, { "pic": "2.jpg", "name": "Name2" }, { "pic": "3.jpg", "name": "Name3" } ] } My goal is to convert it ...

Weaknesses found in the React Js library bundled with create-react-app

Each time I initiate a new react project using npx create-react-app <AppName>, the following vulnerabilities are detected: 96 vulnerabilities found - Packages audited: 1682 Severity: 65 Moderate | 30 High | 1 Critical Node Version: v14.18.1 Npm: 7.20 ...

Guide on changing image source using a function

I am looking to dynamically set the img src="" attribute using a JavaScript function that changes the image based on a variable and checks its values: Here is the JavaScript code in the file: function myFunctionstatus(){ var ledactual = document.getE ...

Error Encountered with Custom Ajax File Uploader's .AjaxSubmit() Function

I am working on a multipart form that allows users to upload images using AJAX. Here is the HTML code: <form name="mainform" id="mainform" class="form_step" action="" method="POST" enctype="multipart/form-data"> <!-- This image acts li ...

jQuery scrolling table

After struggling with this code for the past 48 hours, I'm reaching out for some guidance. Can someone help point me in the right direction? The task at hand is to create a table that functions similarly to a jQuery calendar. Clicking the next button ...

How can you turn off CSS3 animations for browsers that don't support them

Upon page load, a fade-in animation is applied to the main container. Although it functions properly in most browsers, it seems to have an issue in IE(9). Is there a method to identify if the user's browser does not support CSS3 animations and disabl ...

What is the method for selecting the desired month on a primeng calendar with multiple selection enabled?

I am looking for a solution to make my inline primeNg Calendar display the month of a specific date in the model, and when I remove dates from the model, I want it to show the current month. I have tried using defaultDate={{value}} and minDate={{value}}, a ...

Effortlessly make a ThreeJs object follow the mouse's movement

I'm currently working on a project where I want an object to continuously track the mouse in a more natural manner. Here's what I've accomplished so far: Ensured that the object always looks at the mouse Added easing for a smoother, more n ...

Changing an array into Alamofire parameters using Swift

Currently, I am utilizing the Alamofire library to send a request using the .put method to an external API. When testing with Postman, I have been able to successfully transmit raw JSON data in a specific format that includes both an ID and a quantity for ...

Troubleshooting: Unable to modify value with function in AngularJS

Why can't I change a value using a function in AngularJS? html: <div ng-controler='TestCtrl' id='TestCtrl'> <h1>Test: {{test.name}}</h1> <div ng-hide='showTest'> <div class=&a ...

When the getImageData event is triggered upon loading

Hello, I have a script that identifies transparent and non-transparent pixels. Currently, the result is displayed from a 100px by 100px rectangle on mouseover: var data = ctx.getImageData(100,100, canvas.width, canvas.height).data; During mouseover, it s ...

Steps for making a toggle button with Bootstrap

Initially, I developed a web application using HTML, CSS, and JavaScript. Later on, I was requested to recreate it using Bootstrap as well. While I managed to complete the task successfully, I encountered an issue where toggle buttons in the web app revert ...

Tips for combining or converting JSON files in Azure Cosmos DB

I am currently in the process of setting up a Chatbot using the Microsoft Bot Framework and Azure. My goal is to store the "UserState" in a database for easy user data analysis. I have successfully saved my userState as JSON documents in Azure Cosmos DB. ...

Refreshing the form fields and storing the information using AngularJS

I have successfully implemented a basic form using AngularJS. The issue I am facing is that even after the user enters their details and submits the form, the values remain in the input fields. My goal is to store the details of multiple fields in the con ...

Refresh the flatlist to display new content without uploading items automatically

When I click the save button in my FlatList component within React Native, the data does not reload automatically or render in the FlatList. However, if I manually reload the app, the saved item appears. I've tried various methods to make the data re ...

Problems arising from the implementation of CSS modules in React applications

As a beginner in React, I recently started learning how to utilize CSS modules within my React projects. However, I encountered an error that read: Failed to compile. ./src/components/Header/Header.js Module not found: Can't resolve './Header.mo ...

Eliminate spacing between divs of varying heights

I'm facing an issue with my small gallery of images. Despite having the same width, they vary in height causing the second row to start below the tallest image from the previous row. How can I eliminate these empty spaces while still maintaining the v ...

How can you connect a property to the output of a method in Vue.js when working with TypeScript and vue-property-decorator?

I'm working with a TypeScript single file vue component. I've encountered an issue where the template does not display the values returned by certain component methods. Here's a snippet of the template: <div class="order-items"> ...