Skip to content

JSONSchemaType with TypeScript is broken #2558

@jpilgrim

Description

@jpilgrim

What version of Ajv are you using? Does the issue happen if you use the latest version?

8.17.1

TypeScript version

5.8.3

Ajv options object

// none

JSON Schema

For the bug report, I used the JSON from the documentation https://ajv.js.org/guide/typescript.html#utility-types-for-schemas

{
    "type": "object",
    "properties": {
        "foo": { "type": "integer" },
        "bar": { "type": "string", "nullable": true }
    },
    "required": ["foo"],
    "additionalProperties": false
}

Sample data

It's only about typing.

Your code

It's similar to the code in the documentation https://ajv.js.org/guide/typescript.html#utility-types-for-schemas, except that the JSON string is not written as string literal as part of the initialization, but separately

const schemaFromObject = {
        "type": "object",
        "properties": {
            "foo": { "type": "integer" },
            "bar": { "type": "string", "nullable": true }
        },
        "required": ["foo"],
        "additionalProperties": false
    }
const schema: JSONSchemaType<MyData> = schemaFromObject;

I also have variants reading the JSON from other files etc., which are also not working. But this is the smallest change compared to the documentation.

Expected Result

This code should work similar to https://ajv.js.org/guide/typescript.html#utility-types-for-schemas

Actual Result

A type error is emitted (by tsc):

Type '{ type: string; properties: { foo: { type: string; }; bar: { type: string; nullable: boolean; }; }; required: string[]; additionalProperties: boolean; }' is not assignable to type 'JSONSchemaType<MyData>'.
  Type '{ type: string; properties: { foo: { type: string; }; bar: { type: string; nullable: boolean; }; }; required: string[]; additionalProperties: boolean; }' is not assignable to type '({ anyOf: readonly UncheckedJSONSchemaType<MyData, false>[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<string, UncheckedJSONSchemaType<...>> | undefined; definitions?: Record<...> | undefined; }) | ({ ...; } & { ...; })'.
    Type '{ type: string; properties: { foo: { type: string; }; bar: { type: string; nullable: boolean; }; }; required: string[]; additionalProperties: boolean; }' is not assignable to type '{ oneOf: readonly UncheckedJSONSchemaType<MyData, false>[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<string, UncheckedJSONSchemaType<...>> | undefined; definitions?: Record<...> | undefined; }'.
      Property 'oneOf' is missing in type '{ type: string; properties: { foo: { type: string; }; bar: { type: string; nullable: boolean; }; }; required: string[]; additionalProperties: boolean; }' but required in type '{ oneOf: readonly UncheckedJSONSchemaType<MyData, false>[]; }'.ts(2322)
json-schema.d.ts(25, 5): 'oneOf' is declared here.
---
const schema: JSONSchemaType<MyData>

Remarks

There are a lot of related reports, here is only a list of some of them:

While one can argue in some cases that the schema has to be defined differently, I would say due to the large number of reports and even the example in the documentation failing, there is a fundamental problem in the type definition somewhere.

Fortunately there is a simple workaround:

const schema = schemaFromObject  as JSONSchemaType<MyData>;

Of course, this does not check the schema at all.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions