Search code examples
typescriptajv

Ajv - how to mark inner schema as optional?


Given the following ajv ( v8.11.2 ) sample schema

import Ajv, { JSONSchemaType } from "ajv";

interface MyType {
    myProp?: OtherType;
}

interface OtherType {
    foo: string;
    bar: number;
}

const otherSchema: JSONSchemaType<OtherType> = {
    type: 'object',
    properties: {
        foo: { type: 'string', minLength: 1 },
        bar: { type: 'number' },
    },
    required: ['foo', 'bar'],
    additionalProperties: false
};

const mySchema: JSONSchemaType<MyType> = {
    type: 'object',
    properties: {
        myProp: otherSchema,
    },
    required: [],
    additionalProperties: false,
};

I get the following error

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

I think this is because TS doesn't know that myProp of mySchema might be undefined, although it does not exist in the required array.

Do you have any ideas how to fix the schema?


Solution

  • You should be able to do the following:

    import { JSONSchemaType } from "ajv";
    
    interface OtherType {
      foo: string;
      bar: number;
    }
    
    interface MyType {
      myProp?: OtherType;
    }
    
    export const otherSchema: JSONSchemaType<OtherType> = {
      type: "object",
      properties: {
        foo: { type: "string", minLength: 1 },
        bar: { type: "number" }
      },
      required: ["foo", "bar"],
      additionalProperties: false
    };
    
    export const mySchema: JSONSchemaType<MyType> = {
      type: "object",
      properties: {
        // nest your objects inside "properties"
        myProp: {
          ...otherSchema,
          nullable: true // this nullable param is important!
        }
      },
      required: [],
      additionalProperties: false
    };
    

    Here is a working example:

    https://codesandbox.io/s/ajv-schema-json-nested-qu9e7q?file=/src/schemas.ts