Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSONSchemaType fails wiht type when a field is declared nullable #2283

Open
gpad opened this issue May 26, 2023 · 2 comments
Open

JSONSchemaType fails wiht type when a field is declared nullable #2283

gpad opened this issue May 26, 2023 · 2 comments

Comments

@gpad
Copy link

gpad commented May 26, 2023

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

8.12.0

Ajv options object

export const ajv = new Ajv({ strict: true })

I'm using Typescript

interface MyType {
  id: string
  value: string | null
}

const MySchema: JSONSchemaType<MyType> = {
  type: "object",
  properties: {
    id: { type: "string" },
    value: { type: "string", nullable: true },
  },
}
export const validateMySchema = ajv.compile<MyType>(MySchema)

I'm getting this issue:

src/user/validation.ts:13:7 - error TS2322: Type '{ type: "object"; properties: { id: { type: "string"; }; value: { type: "string"; nullable: true; }; }; }' is not assignable to type 'JSONSchemaType<MyType>'.
  The types of 'properties.value' are incompatible between these types.
    Type '{ type: "string"; nullable: true; }' is not assignable to type '{ $ref: string; } | ({ anyOf: readonly UncheckedJSONSchemaType<string | null, false>[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<...> | undefined; definitions?: Record<...> | undefined; } & { ...; }) | ({ ...; } & ... 1 more ... & { ...; }) | ({ ...; } & ... 2...'.
      Types of property 'nullable' are incompatible.
        Type 'true' is not assignable to type 'false'.

13 const MySchema: JSONSchemaType<MyType> = {

Also adding null as type:

const MySchema: JSONSchemaType<MyType> = {
  type: "object",
  properties: {
    id: { type: "string" },
    value: { type: ["string", "null"], nullable: true },
  },
}
export const validateMySchema = ajv.compile<MyType>(MySchema)

I have the same error:

src/user/validation.ts:13:7 - error TS2322: Type '{ type: "object"; properties: { id: { type: "string"; }; value: { type: ("string" | "null")[]; nullable: true; }; }; }' is not assignable to type 'JSONSchemaType<MyType>'.
  The types of 'properties.value' are incompatible between these types.
    Type '{ type: ("string" | "null")[]; nullable: true; }' is not assignable to type '{ $ref: string; } | ({ anyOf: readonly UncheckedJSONSchemaType<string | null, false>[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<...> | undefined; definitions?: Record<...> | undefined; } & { ...; }) | ({ ...; } & ... 1 more ... & { ...; }) | ({ ...; } & ... 2...'.
      Types of property 'nullable' are incompatible.
        Type 'true' is not assignable to type 'false'.

13 const MySchema: JSONSchemaType<MyType> = {

also removing the nullable, same issue:

const MySchema: JSONSchemaType<MyType> = {
  type: "object",
  properties: {
    id: { type: "string" },
    value: { type: ["string", "null"] },
  },
}
export const validateMySchema = ajv.compile<MyType>(MySchema)
Type '{ type: "object"; properties: { id: { type: "string"; }; value: { type: ("string" | "null")[]; }; }; }' is not assignable to type 'JSONSchemaType<MyType>'.
  The types of 'properties.value' are incompatible between these types.
    Type '{ type: ("string" | "null")[]; }' is not assignable to type '{ $ref: string; } | ({ anyOf: readonly UncheckedJSONSchemaType<string | null, false>[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<...> | undefined; definitions?: Record<...> | undefined; } & { ...; }) | ({ ...; } & ... 1 more ... & { ...; }) | ({ ...; } & ... 2...'.
      Type '{ type: ("string" | "null")[]; }' is not assignable to type '{ type: "string"; } & StringKeywords & { allOf?: readonly UncheckedPartialSchema<string | null>[] | undefined; anyOf?: readonly UncheckedPartialSchema<string | null>[] | undefined; ... 4 more ...; not?: UncheckedPartialSchema<...> | undefined; } & { ...; } & { ...; }'.
        Type '{ type: ("string" | "null")[]; }' is not assignable to type '{ type: "string"; }'.
          Types of property 'type' are incompatible.
            Type '("string" | "null")[]' is not assignable to type '"string"'.

13 const MySchema: JSONSchemaType<MyType> = {

@epoberezkin
Copy link
Member

JSONSchemaType equates "nullable" to optional property definition, string | null is not supported (I think)

cc @erikbrinkman am I right?

@erikbrinkman
Copy link
Collaborator

erikbrinkman commented Jul 29, 2023

Yes, for ajv 8, nullable actually means undefined not null. the v9 branch has a version of the schema capable of recognizing the difference that you can patch in if you want if you really want. Also note, that JSONSchemaType requires that you use the required keyword, which you probably want to specify in this case.

See:

type Nullable<T> = undefined extends T
? {
nullable: true
const?: null // any non-null value would fail `const: null`, `null` would fail any other value in const
enum?: Readonly<(T | null)[]> // `null` must be explicitly included in "enum" for `null` to pass
default?: T | null
}
: {
nullable?: false
const?: T
enum?: Readonly<T[]>
default?: T
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants