ajv icon indicating copy to clipboard operation
ajv copied to clipboard

typescript `JSONSchemaType`

Open loynoir opened this issue 1 year ago • 2 comments

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

Ajv version 8.11.0

Ajv options object


JSON Schema


Sample data


Your code

import type { JSONSchemaType } from 'ajv'
import Ajv from 'ajv'
type MyData = {
    [id: number]: 42;
}

// generated from `typescript-json-schema tsconfig.json MyData`
const schemaMyData: JSONSchemaType<MyData> = {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "additionalProperties": false,
    "patternProperties": {
        "^[0-9]+$": {
            "enum": [
                42
            ],
            "type": "number"
        }
    },
    "type": "object"
}

const ajv = new Ajv()

const validateMyData = ajv.compile(schemaMyData)
validateMyData({ "a1": 42 }) // false
validateMyData({ "11": 24 }) // false
validateMyData({ "11": 42 }) // true

Validation result, data AFTER validation, error messages

$ typescript-json-schema tsconfig.json MyData

schema

const schemaMyData: JSONSchemaType<MyData> = {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "additionalProperties": false,
    "patternProperties": {
        "^[0-9]+$": {
            "enum": [
                42
            ],
            "type": "number"
        }
    },
    "type": "object"
}

got ts error

Type '{ $schema: string; additionalProperties: false; patternProperties: { "^[0-9]+$": { enum: number[]; type: string; }; }; type: "object"; }' is not assignable to type 'UncheckedJSONSchemaType<MyData, false>'.
  Types of property '"patternProperties"' are incompatible.
    Type '{ "^[0-9]+$": { enum: number[]; type: string; }; }' is not assignable to type 'Record<string, UncheckedJSONSchemaType<unknown, false>>'.
      Property '"^[0-9]+$"' is incompatible with index signature.
        Type '{ enum: number[]; type: string; }' is not assignable to type 'UncheckedJSONSchemaType<unknown, false>'.
          Type '{ enum: number[]; type: string; }' is not assignable to type '{ type: readonly never[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<string, UncheckedJSONSchemaType<Known, true>> | undefined; definitions?: Record<...> | undefined; }'.
            Type '{ enum: number[]; type: string; }' is not assignable to type '{ type: readonly never[]; }'.
              Types of property 'type' are incompatible.
                Type 'string' is not assignable to type 'readonly never[]'.ts(2322)

What results did you expect? no typescript error

Are you going to resolve the issue?

loynoir avatar Jul 25 '22 04:07 loynoir

we face the same issue, is there a solution for this problem? thank you

wuriyanto48 avatar Aug 07 '22 05:08 wuriyanto48

this is the best i could think to overcome your issue i ended up putting undefined on type an marking it as any

type numericKeyed42 = {
	[K: `${number}`]: 42;
};

function test(schema: SomeSchema, data: unknown) {
	const valid = ajv.validate(schema, data);
	if (valid) console.log("Valid!");
	else console.log("Invalid!");
}

const schema: SchemaType<numericKeyed42> = {
	type: "object",
	propertyNames: { type: "string", pattern: "^\\d+$" },
	additionalProperties: { type: undefined as any, const: 42 },
	required: [],
};

const schema1: SchemaType<numericKeyed42> = {
	type: "object",
	patternProperties: {
		"^\\d+$": { type: undefined as any, const: 42 },
	},
	additionalProperties: false,
	required: [],
};

const dataI = {
	"10": 42,
	"12": 42,
	"424": 42,
	teat: 42,
};
const dataV = {
	"10": 42,
	"12": 42,
	"424": 42,
};

test(schema, dataV);   // prints Valid!
test(schema, dataI);   // prints Inalid!
test(schema1, dataV);  // prints Valid!
test(schema1, dataI);  // prints Inalid!

HakamaObi avatar Sep 23 '22 17:09 HakamaObi