Skip to content

Commit

Permalink
add refs varaible for jtd validation
Browse files Browse the repository at this point in the history
There seems to be some weird behavior with typescript when refs was left
to default. By specifying it manually the behavior was fixed.

fixes #2167
  • Loading branch information
erikbrinkman committed Jul 29, 2023
1 parent 490eb8c commit 80db1da
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 5 deletions.
2 changes: 1 addition & 1 deletion lib/compile/jtd/types.ts
Expand Up @@ -13,4 +13,4 @@ export const jtdForms = [
"ref",
] as const

export type JTDForm = (typeof jtdForms)[number]
export type JTDForm = typeof jtdForms[number]
2 changes: 1 addition & 1 deletion lib/compile/rules.ts
Expand Up @@ -2,7 +2,7 @@ import type {AddedKeywordDefinition} from "../types"

const _jsonTypes = ["string", "number", "integer", "boolean", "null", "object", "array"] as const

export type JSONType = (typeof _jsonTypes)[number]
export type JSONType = typeof _jsonTypes[number]

const jsonTypes: Set<string> = new Set(_jsonTypes)

Expand Down
10 changes: 8 additions & 2 deletions lib/core.ts
Expand Up @@ -340,7 +340,10 @@ export default class Ajv {
validate<T>(schema: Schema | JSONSchemaType<T> | string, data: unknown): data is T
// Separated for type inference to work
// eslint-disable-next-line @typescript-eslint/unified-signatures
validate<T>(schema: JTDSchemaType<T>, data: unknown): data is T
validate<T, R extends Record<string, unknown>>(
schema: JTDSchemaType<T, R>,
data: unknown
): data is T
// This overload is only intended for typescript inference, the first
// argument prevents manual type annotation from matching this overload
validate<N extends never, T extends SomeJTDSchemaType>(
Expand Down Expand Up @@ -371,7 +374,10 @@ export default class Ajv {
compile<T = unknown>(schema: Schema | JSONSchemaType<T>, _meta?: boolean): ValidateFunction<T>
// Separated for type inference to work
// eslint-disable-next-line @typescript-eslint/unified-signatures
compile<T = unknown>(schema: JTDSchemaType<T>, _meta?: boolean): ValidateFunction<T>
compile<T = unknown, R extends Record<string, unknown> = Record<string, unknown>>(
schema: JTDSchemaType<T, R>,
_meta?: boolean
): ValidateFunction<T>
// This overload is only intended for typescript inference, the first
// argument prevents manual type annotation from matching this overload
compile<N extends never, T extends SomeJTDSchemaType>(
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -11,7 +11,7 @@
],
"scripts": {
"eslint": "eslint \"lib/**/*.ts\" \"spec/**/*.*s\" --ignore-pattern spec/JSON-Schema-Test-Suite",
"prettier:write": "prettier --write \"./**/*.{json,yaml,js,ts}\"",
"prettier:write": "prettier --write --cache \"./**/*.{json,yaml,js,ts}\"",
"prettier:check": "prettier --list-different \"./**/*.{json,yaml,js,ts}\"",
"test-spec": "cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register \"spec/**/*.spec.{ts,js}\" -R dot",
"test-codegen": "nyc cross-env TS_NODE_PROJECT=spec/tsconfig.json mocha -r ts-node/register 'spec/codegen.spec.ts' -R spec",
Expand Down
47 changes: 47 additions & 0 deletions spec/types/jtd-schema.spec.ts
Expand Up @@ -353,12 +353,30 @@ describe("JTDSchemaType", () => {
})

it("should typecheck ref schemas", () => {
const ajv = new _Ajv()
const refs: JTDSchemaType<number[], {num: number}> = {
definitions: {
num: {type: "float64"},
},
elements: {ref: "num"},
}

// test that ajv.validate captures ref data type
const validData: unknown = [0]
if (ajv.validate(refs, validData)) {
const postValidation: number[] = validData
postValidation[0].should.equal(0)
}
should.not.exist(ajv.errors)

// test that ajv.compile captures ref data type
const validate = ajv.compile(refs)
if (validate(validData)) {
const postValidation: number[] = validData
postValidation[0].should.equal(0)
}
should.not.exist(validate.errors)

const missingDef: JTDSchemaType<number[], {num: number}> = {
// @ts-expect-error
definitions: {},
Expand Down Expand Up @@ -393,6 +411,35 @@ describe("JTDSchemaType", () => {
void [refs, missingDef, missingType, nullRefs, refsNullOne, refsNullTwo]
})

it("should typecheck nested ref schemas", () => {
const ajv = new _Ajv()
const schema: JTDSchemaType<{str: string; ref: number}, {num: number}> = {
definitions: {
num: {type: "int32"},
},
properties: {
ref: {ref: "num"},
str: {type: "string"},
},
}

// test that ajv.validate captures ref data type
const validData: unknown = {str: "", ref: 0}
if (ajv.validate(schema, validData)) {
const str: string = validData.str
str.should.equal("")
}
should.not.exist(ajv.errors)

// test that ajv.compile captures ref data type
const validate = ajv.compile(schema)
if (validate(validData)) {
const str: string = validData.str
str.should.equal("")
}
should.not.exist(validate.errors)
})

it("should typecheck metadata schemas", () => {
const meta: JTDSchemaType<number> = {type: "float32", metadata: {key: "val"}}
const emptyMeta: JTDSchemaType<unknown> = {metadata: {key: "val"}}
Expand Down

0 comments on commit 80db1da

Please sign in to comment.