0

I have field called platform which can either be a string or a string[] this field can also be nullable/undefined (not passed).

typescript interface

export interface IEntityLeaderboardQuery {
    rank: string;
    entity_types: string[] | string;
    country?: string | undefined;
    region?: string | undefined;
    start_date: string;
    end_date: string;
    top?: string | undefined;
    platform?: string[] | string | undefined;
}

json schema

export const EntityLeaderboardQuerySchema: JSONSchemaType<IEntityLeaderboardQuery> = {
    type: "object",
    properties: {
        rank: { type: "string" },
        entity_types: {
            oneOf: [
                {
                    type: "string",
                },
                {
                    type: "array",
                    items: { type: "string" },
                },
            ],
        },
        country: { type: "string", nullable: true },
        region: { type: "string", nullable: true },
        start_date: { type: "string" },
        end_date: { type: "string" },
        top: { type: "string", nullable: true },
        platform: {
            oneOf: [
                {
                    type: "string",
                    nullable: true,
                },
                {
                    type: "array",
                    items: { type: "string" },
                    nullable: true,
                },
            ],
        },
    },
    required: ["rank", "entity_types", "start_date", "end_date"],
    additionalProperties: false,
};

As you can see ive attempted to add nullable field to both objects within the oneOf array. However there is still an issue with the types

[ERROR] 11:07:49 ⨯ Unable to compile TypeScript: src/api/leaderboard/entity/entity-leaderboard.interface.ts:43:14 - error TS2322: Type '{ type: "object"; properties: { rank: { type: "string"; }; entity_types: { oneOf: ({ type: "string"; } | { type: "array"; items: { type: "string"; }; })[]; }; country: { type: "string"; nullable: true; }; region: { ...; }; start_date: { ...; }; end_date: { ...; }; top: { ...; }; platform: { ...; }; }; required: ("ra...' is not assignable to type 'UncheckedJSONSchemaType<IEntityLeaderboardQuery, false>'. Type '{ type: "object"; properties: { rank: { type: "string"; }; entity_types: { oneOf: ({ type: "string"; } | { type: "array"; items: { type: "string"; }; })[]; }; country: { type: "string"; nullable: true; }; region: { ...; }; start_date: { ...; }; end_date: { ...; }; top: { ...; }; platform: { ...; }; }; required: ("ra...' is not assignable to type '{ type: "object"; additionalProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; unevaluatedProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; ... 7 more ...; maxProperties?: number | undefined; } & { ...; } & { ...; } & { ...; }'. Type '{ type: "object"; properties: { rank: { type: "string"; }; entity_types: { oneOf: ({ type: "string"; } | { type: "array"; items: { type: "string"; }; })[]; }; country: { type: "string"; nullable: true; }; region: { ...; }; start_date: { ...; }; end_date: { ...; }; top: { ...; }; platform: { ...; }; }; required: ("ra...' is not assignable to type '{ type: "object"; additionalProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; unevaluatedProperties?: boolean | UncheckedJSONSchemaType<unknown, false> | undefined; ... 7 more ...; maxProperties?: number | undefined; }'. The types of 'properties.platform' are incompatible between these types. Type '{ oneOf: ({ type: "string"; nullable: boolean; } | { type: "array"; items: { type: "string"; nullable: boolean; }; nullable: boolean; })[]; }' is not assignable to type '{ $ref: string; } | (UncheckedJSONSchemaType<string | string[] | undefined, false> & { nullable: true; const?: undefined; enum?: readonly (string | string[] | null | undefined)[] | undefined; default?: string | ... 2 more ... | undefined; })'. Type '{ oneOf: ({ type: "string"; nullable: boolean; } | { type: "array"; items: { type: "string"; nullable: boolean; }; nullable: boolean; })[]; }' is not assignable to type '{ type: "array"; items: UncheckedJSONSchemaType<string, false>; contains?: UncheckedPartialSchema | undefined; minItems?: number | undefined; ... 4 more ...; additionalItems?: undefined; } & { ...; } & { ...; } & { ...; }'. Type '{ oneOf: ({ type: "string"; nullable: boolean; } | { type: "array"; items: { type: "string"; nullable: boolean; }; nullable: boolean; })[]; }' is missing the following properties from type '{ type: "array"; items: UncheckedJSONSchemaType<string, false>; contains?: UncheckedPartialSchema | undefined; minItems?: number | undefined; ... 4 more ...; additionalItems?: undefined; }': type, items

43 export const EntityLeaderboardQuerySchema: JSONSchemaType = {

ajv: 8.6.2
typescipt: 4.3.5

https://replit.com/join/ngjynszvjr-kaykhan

1
  • At first undefined is not a type in json, it is however supported in json schema through the "optional": true property, if you have to support null type. Also: normally you can use {type: "null"} but as @Ryan wrote, he has problem using "null" as a type (this depends on the json validator you are using). At last, I would recommend trying using a lib like npmjs.com/package/json-schema-to-typescript just to convert your typescript definition to a json schema. As of today, the json schema is still a draft Commented Oct 13, 2021 at 10:03

2 Answers 2

2

It doesn't compile as typescript thinks it's trying to assign an optional type to a non-optional type.

The problem arises since you are using the assignment of nullable: true to the items of oneOf, you must specify outside since the property is using optional chaining ? platform?: string[] | string

platform: {
  nullable: true, //<-- nullable Here
  type: ['string', 'array'], //<-- when using "nullable" you must specify the types
  oneOf: [
    { 
      type: 'string' 
    },
    {
      type: 'array',
      items: { type: 'string' },
    }
  ]
}

If you are using strict mode with Ajv you will probably get a warning:

strict mode: use allowUnionTypes to allow union type keyword at "#/properties/platform" (strictTypes)

Enabling allowUnionTypes should work:

const ajv = new Ajv({ allowUnionTypes: true })
Sign up to request clarification or add additional context in comments.

Comments

0

I had a similar situation and this worked for me:

oneOf: [
    {
        type: "string",
    },
    {
        type: "array",
        items: { type: "string" },
    },
    {
        type: "object",
        nullable: true,
    },
],

Using { type: "null" } did not work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.