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

Representing union type in schema #2081

Closed
vongohren opened this issue Sep 5, 2022 · 8 comments
Closed

Representing union type in schema #2081

vongohren opened this issue Sep 5, 2022 · 8 comments

Comments

@vongohren
Copy link

vongohren commented Sep 5, 2022

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

Your typescript code

type Typez = string | string[];
interface Test {
 typez: Types
}

const schema: JSONSchemaType<Test> = {
  type: "object",
  properties: {
    typez: {
      type: [{ type: "string"}, {type: "array", items: {type:"string"}}]
    }
  }
}

Typescript compiler error messages

Type '{ type: "object"; properties: { typez: { type: ({ type: string; } | { type: string; items: { type: string; }; })[]; }; }; }' is not assignable to type 'UncheckedJSONSchemaType<Test, false>'.
  The types of 'properties.typez' are incompatible between these types.
    Type '{ type: ({ type: string; } | { type: string; items: { type: string; }; })[]; }' is not assignable to type '{ $ref: string; } | (UncheckedJSONSchemaType<Typez, false> & { const?: Typez | undefined; enum?: readonly Typez[] | undefined; default?: Typez | undefined; })'.
      Type '{ type: ({ type: string; } | { type: string; items: { type: string; }; })[]; }' is not assignable to type '{ type: "array"; items: UncheckedJSONSchemaType<string, false>; contains?: UncheckedPartialSchema<string> | undefined; minItems?: number | undefined; ... 4 more ...; additionalItems?: undefined; } & { ...; } & { ...; } & { ...; }'.
        Property 'items' is missing in type '{ type: ({ type: string; } | { type: string; items: { type: string; }; })[]; }' but required in type '{ type: "array"; items: UncheckedJSONSchemaType<string, false>; contains?: UncheckedPartialSchema<string> | undefined; minItems?: number | undefined; ... 4 more ...; additionalItems?: undefined; }'.ts(2322)

Describe the change that should be made to address the issue?
How shall I be able to represent the current type with ajv?
I have not understood how this PR helped: #1302
Or this: #134

Are you going to resolve the issue?
I will resolve when I get some feedback

@vongohren
Copy link
Author

I believe this can be solved with anyOf, instead of type inside the "typez", please confirm and this can be closed

@epoberezkin
Copy link
Member

the correct syntax for type keyword value is either a string or an array of strings, not an array of objects as in the example.

{type: ["string", "array"], items: {type:"string"}}

anyOf can be cleaner indeed.

@joey-squid
Copy link

joey-squid commented Dec 15, 2022

The following doesn't seem to compile either. Is it supposed to?

const schema: JSONSchemaType<Test> = {
  type: 'object',
  properties: {
    typez: {
      type: {
        anyOf: [  // or oneOf
          { type: 'string' },
          { type: 'array', items: { type: 'string' } },
        ],
      },
    },
  },
};

I could be completely off, but it looks to me like https://github.com/ajv-validator/ajv/blob/master/lib/types/json-schema.ts#L63 is incorrectly handling the case where T extends both number and any[].

@joey-squid
Copy link

For that matter, neither does

const schema: JSONSchemaType<Test> = {
  type: 'object',
  properties: {
    typez: {
      type: {type: ["string", "array"], items: {type:"string"}}
    },
  },
};

@jeremycare
Copy link

We are facing the same issue, why is that closed?
Is it an issue with json-schema on its own? Or specific to AJV?

@epoberezkin
Copy link
Member

epoberezkin commented Jan 17, 2023

The issue is closed because the original question was answered.

The question in the comment is different - JSONSchemaType utility probably does not support a union array and scalar type – it is a limitation.

Both JSON Schema and Ajv support such unions, it is only related to JSONSchemaType - you can use Ajv without it though.

Arguably, an untagged union of array and scalar should not be used in JSON APIs, as it can't be supported by many programming languages, for that reason it also won't be supported by JTD (JSON Type Definition - an alternative JSON schema language specification supported by Ajv, that maps well to type systems of a large number of languages).

Instead it is better to use a discriminated union with a tag.

@jeremycare
Copy link

Thanks for the update

@SMJSGaming
Copy link

SMJSGaming commented Jul 24, 2023

Sadly I'm facing a situation where it would be reasonable to use a union. That being a union of string or null, something basically every language can handle. In my case it makes it almost impossible to use ajv in typescript without using any casts which shouldn't have to exist.

Additionally I find it odd that nullable doesn't cover null within a union, which would've solved my problem otherwise.

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

No branches or pull requests

5 participants