question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

JTDSchema with generics

See original GitHub issue

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

Your typescript code

import { JTDSchemaType } from 'ajv/dist/jtd'

type PropType = 'a' | 'b' | 'c'

type Obj<T extends PropType> = {
    type: T
}

// fails
function getObjSchema<T extends PropType>(propType: T): JTDSchemaType<Obj<T>> {
    return {
        properties: {
            type: { enum: [propType] },
        },
    }
}

// passes
function getObjSchemaA(propType: 'a'): JTDSchemaType<Obj<'a'>> {
    return {
        properties: {
            type: { enum: [propType] },
        },
    }
}

Typescript compiler error messages

Type '{ properties: { type: { enum: T[]; }; }; }' is not assignable to type 'JTDSchemaType<Obj<T>, Record<string, never>>'.
  Type '{ properties: { type: { enum: T[]; }; }; }' is not assignable to type '[undefined extends T ? never : "type"] extends [never] ? { properties?: Record<string, never> | undefined; } : { properties: { [K in undefined extends T ? never : "type"]: JTDSchemaType<Obj<T>[K], Record<...>>; }; }'.ts(2322)

Describe the change that should be made to address the issue? Not sure.

Are you going to resolve the issue? No.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
erikbrinkmancommented, Jun 25, 2021

I agree it’s inelegant. Whether to close it is potentially up to @epoberezkin. I think from the definition of JTD Schema, the type itself has to be invariant, which as stated above, is the root cause, and therefore unfixable. There may be ways to create a type that’s less strict that is covariant, but I think that’s probably not feasible with the same guarantees.

The other avenue I see is JTDDataType. This infers the resulting type from the schema type instead of requiring annotation of the schema itself. Going off of my example above, you can do something like:

const myASchemaData = getObjMySchema<'a'>('a');
type MyAResult = JTDDataType<typeof myASchema>

MyResult here is structurally equivalent to Obj<'a'>. Ideally if you specify the type of getObjMySchema correctly, then you should be fine. ajv should infer a proper validated type from it. avj has some trouble with inference due to the complexity of the overloads, but this more complicated version also worked with a simpler stubbed out validate:

declare function validate<T extends SomeJTDSchemaType>(schema: T, obj: unknown): JTDDataType<T>;

function myValidate<T extends PropType>(propType: T, obj: unknown): JTDDataType<MySchema<T>> {
  const schema = getObjMySchema(propType);
  const result = validate(schema, obj);
  return result;
}

const aObj: Obj<'a'> = myValidate('a', null);

here the type declaration at the end isn’t necessary, it’s a validation that the result of myValidate is actually assignable to Obj<'a'>.

1reaction
NonSpicyBurritocommented, Jun 24, 2021

I don’t think the problem here is how JTDSchemaType is defined. The problem here fundamentally is that T extends PropType can include more than one value from PropType definition, and the schema is defined to allow only exactly one value - so it indeed does not match your data type.

cc @erikbrinkman

How should I go about typing the getObjSchema function then? Intuitively I thought how I typed it was the way to go.

Read more comments on GitHub >

github_iconTop Results From Across the Web

JTD generics type utility · Issue #1616 · ajv-validator/ajv - GitHub
I've already tried using a generic function, but JTDSchemaType seems to not like it. e.g. ... Doing this seems to prevent getting any...
Read more >
Using with TypeScript - Ajv JSON schema validator
You can use JTD schema to construct the type of data using utility type JTDDataType. JSON Type Definition. import Ajv, {JTDDataType} from "ajv/dist/jtd" ......
Read more >
Using Dynamic References to Support Generic Types
The topic in this post can apply to any programming paradigm where you have a defined data model and support for something like...
Read more >
Can i just paste jtd as typescript type syntax? - Stack Overflow
JTDDataType is a utility type from ajv, which converts a jtd schema type to the related valid types in typescript. Security notes:.
Read more >
Data.JSON.Schema.Generic - Hackage
Data.JSON.Schema.Generic. Description. Generic derivation of schemas. The schemas generated match the JSON generated by type 'generic-aeson' package.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found