Search code examples
javascripttypescriptzod

How to define the type for a nullish value with schema from Zod


I have a type defined with zod.

Am inexperienced with TypeScript.

The zod object looks like this:

import z from 'zod';
const clientSchema = z.object({
  name: z.string(),
  details: z.object({
    detail1: z.string().optional()
    }
  }
);
export type ClientSchema = z.infer<typeof clientSchema>;

Assigning the details of a client of type ClientSchema, I was hoping to be able to annotate it's type like this:

const details = {
  detail1: <string|null|undefined> ''
}

But TypeScript complains:

Types of property 'detail1' are incompatible. Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'."

So now I have created a separate Schema for details:

export const detailSchema = z.object({
    detail1: z.string().optional() ,
});
export type DetailSchema = z.infer<typeof detailSchema>;

And then declare the object:

const details: DetailSchema = {
  detail1: 'a string'
}

Is that the expected/recommended approach for sub-objects?


Solution

  • You can have nullable objects as well, in the case you want a property to be null or undefined you can do

    property: z.string().nullable().optional(), in your case this would be:

    const clientSchema = z.object({
      name: z.string(),
      details: z.object({
        detail1: z.string().nullable().optional()
      })
    });
    

    Which should give you

    type ClientSchema = {
        name: string;
        details: {
            detail1?: string | null | undefined;
        };
    }
    

    From this you can extrapolate the details schema as

    type DetailSchema = ClientSchema["details"];

    which will give you

    type DetailSchema = {
        detail1?: string | null | undefined;
    }
    

    Which you can use as follows:

    const details: DetailsSchema = {
      details1: ""  // string | null | undefined
    }