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

Natively make ajv validators typeguards in TS (integrate with json-schema-to-ts) #2091

Open
ThomasAribart opened this issue Sep 12, 2022 · 7 comments

Comments

@ThomasAribart
Copy link

ThomasAribart commented Sep 12, 2022

What version of Ajv you are you using?
NA

What problem do you want to solve?

In TS, it would be neat to make ajv.validate and ajv.compile outputs typeguards.

I maintain json-schema-to-ts which would allow such feature, as long as the schema is defined with the as const statement. The lib is heavily tested against ajv, and there are even examples on how to integrate with ajv.

This is something that is frequently done in many projects, and it would be cool to have this feature natively in the lib.

What do you think is the correct solution to problem?

Some schemas (for instance, those imported from json files), will NOT be defined with the as const statement. Besides, json-schema-to-ts has impacts on IDE performances (it comes with some deeply nested type computations), and FromSchema can accept configuration options such as deserialization patterns.

So I think the best solution is to make such feature opt-in, but I'm not sure exactly how. Maybe with a type overload:

import Ajv, { TypechargedAjv } from 'ajv'

const ajv = new Ajv() as TypechargedAjv<SomeFromSchemaOptions>

const mySchema = { ... } as const

if (ajv.validate(mySchema, someData)) {
   ... // someData is correctly typed
}

Will you be able to implement it?

Definitely yes.

Note: There are some other solutions out there, but I think json-schema-to-ts is the best for this need. Some links if you want to check them:

@GabenGar
Copy link

Validate function is already typeguarded, you just need to pass the generic to it.

@ThomasAribart
Copy link
Author

ThomasAribart commented Oct 13, 2022

Sorry I probably wasn't clear enough: I was talking about making validators typeguards without having to input the valid data type. I did not add a generic in my example code by purpose.

If you define your schemas with the as const statement, the generic type of the schema is enough to infer the type of valid data, that's what json-schema-to-ts does.

It may seem like a small difference, but it is a HUGE one! Providing manually the type of valid data:

  • Takes time from the developer and increase the codebase size
  • Means that you duplicate your types between json-schemas and types, which increases risks of bug

Sure, you can always provide FromSchema<typeof mySchema> as your generic, but there also, there may be room for human error (might as well provide only one input).

@epoberezkin
Copy link
Member

epoberezkin commented Oct 13, 2022

Overloads for compile should infer the type from the passed schema already - check this: https://github.com/ajv-validator/ajv/blob/master/lib/core.ts#L371

@ThomasAribart
Copy link
Author

ThomasAribart commented Oct 20, 2022

@epoberezkin Can you give me more context on the lines of code you provided ? It's not that easy to understand.

It seems rather like the JSON schema type is inferred from the valid data type but I may be wrong 🤔

I think it would make more sense to infer the valid data type from the schema type as many schemas can represent the same type.

@epoberezkin
Copy link
Member

It seems rather like the JSON schema type is inferred from the valid data type but I may be wrong

it should work both ways - if you provide the schema of known type, the compiler would infer the type of data. There are actually tests for that.

@epoberezkin
Copy link
Member

See this, for example - https://github.com/ajv-validator/ajv/blob/master/spec/types/json-schema.spec.ts

Validating against the schema of known type proves the type of data

@GabenGar
Copy link

@ThomasAribart
Do I understand right that you want a way to automatically infer a valid interface for an input value from JSON schema?
Is this even possible for complex enough schemas full of "$ref"s and "$dynamicAnchor"s?

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

No branches or pull requests

3 participants