Michael Boñon
Michael Boñon

Reputation: 194

What type should I use for a const object in JSONSchemaType in AJV?

I'm writing a validator using AJV and have defined the schema as follows:

const ajv = new Ajv({ allErrors: true, $data: true });

export interface UpdateTaskRequest {
  pathParameters: {
    listId: string;
    taskId: string;
  };
  body: {
    id: string;
    name: string;
    isCompleted?: boolean;
    desc?: string;
    dueDate?: string;
  };
}

export const updateTaskRequestSchema: JSONSchemaType<UpdateTaskRequest> = {
  $schema: "http://json-schema.org/draft-07/schema#",
  type: "object",
  properties: {
    pathParameters: {
      type: "object",
      properties: {
        listId: {
          type: "string",
        },
        taskId: {
          type: "string",
        },
      },
      required: ["listId", "taskId"],
    },
    body: {
      type: "object",
      properties: {
        id: {
          const: { $data: "/pathParameters/taskId" },
        },
        name: {
          type: "string",
          maxLength: 200,
        },
        isCompleted: {
          type: "boolean",
          nullable: true,
        },
        desc: {
          type: "string",
          nullable: true,
          maxLength: 400,
        },
        dueDate: {
          type: "string",
          nullable: true,
          format: "date-time",
        },
      },
      required: ["id", "name"],
    },
  },
  required: ["pathParameters", "body"],
};

I want to validate that body.id is equal to pathParameters.taskId so I used the const keyword in conjunction with the $data reference as explained here.

id: {
  const: { $data: "/pathParameters/taskId" },
},

The problem is I'm getting the following error:

The types of 'properties.id' are incompatible between these types. Type '{ const: { $data: string; }; }' is not assignable to type '{ $ref: string; } | (UncheckedJSONSchemaType<string, false> & { const?: string | undefined; enum?: readonly string[] | undefined; default?: string | undefined; })'. Types of property 'const' are incompatible. Type '{ $data: string; }' is not assignable to type 'string'.ts(2322)

How do I tell the TypeScript compiler that { $data: string; } will eventually resolve to string so as to resolve the above error? I tried the following but it did not work:

id: {
  type: "string",
  const: { $data: "/pathParameters/taskId" },
},

Upvotes: 0

Views: 1300

Answers (2)

S&#233;bastien Loix
S&#233;bastien Loix

Reputation: 646

My simpler workaround

properties: {
  id: {
    type: "string",
    const: { $data: "/pathParameters/taskId" } as unknown as string,
  }
  ...

Upvotes: 0

Michael Bo&#241;on
Michael Bo&#241;on

Reputation: 194

I found a workaround by defining the $data reference in an if/then expression:

export const updateTaskRequestSchema: JSONSchemaType<UpdateTaskRequest> = {
  $schema: "http://json-schema.org/draft-07/schema#",
  type: "object",
  properties: {
    pathParameters: {
      type: "object",
      properties: {
        listId: {
          type: "string",
        },
        taskId: {
          type: "string",
        },
      },
      required: ["listId", "taskId"],
    },
    body: {
      type: "object",
      properties: {
        id: {
          type: "string",
        },
        name: {
          type: "string",
          maxLength: 200,
        },
        isCompleted: {
          type: "boolean",
          nullable: true,
        },
        desc: {
          type: "string",
          nullable: true,
          maxLength: 400,
        },
        dueDate: {
          type: "string",
          nullable: true,
          format: "date-time",
        },
      },
      required: ["id", "name"],
    },
  },
  required: ["pathParameters", "body"],
  if: {
    properties: {
      pathParameters: {
        type: "object",
        properties: {
          taskId: {
            type: "string",
          },
        },
      },
    },
  },
  then: {
    properties: {
      body: {
        type: "object",
        properties: {
          id: {
            const: { $data: "/pathParameters/taskId" },
          },
        },
      },
    },
  },
};

Upvotes: 0

Related Questions