ajv-validator / ajv-validator/ajv-errors

`JSONSchemaType` + `anyOf` corresponding to union over objects cannot correctly determine missing fields

Ouverte
#144 2 commentaires 2 réactions 0 personnes assignées Voir sur GitHub
Langage dominant
TypeScript
Étoiles
289
Forks
21
Métriques de merge des PR
Aucune PR mergée en 30 j

Description

## Problem description
AJV cannot infer which subtype of a union is being used when creating a union over objects. This might be an issue with AJV core, or just an issue with the error handling.

Below is a simple but complete example of the issue:

```typescript
import ajvErrors from 'ajv-errors'
import addFormats from 'ajv-formats'
import Ajv, { JSONSchemaType } from 'ajv'

type UploadAction = {
actionType: 'UPLOAD'
url: string
filename: string
}

type EmailAction = {
actionType: 'EMAIL'
email: string
}

type Action = UploadAction | EmailAction
type Actions = Array

const schema: JSONSchemaType = {
type: 'array',
items: {
anyOf: [
{
type: 'object',
required: ['actionType', 'url', 'filename'],
properties: {
actionType: {
type: 'string',
const: 'UPLOAD',
},
url: {
type: 'string',
},
filename: {
type: 'string',
},
},
},
{
type: 'object',
required: ['actionType', 'email'],
properties: {
actionType: {
type: 'string',
const: 'EMAIL',
},
email: {
type: 'string',
},
},
},
],
},
}

if (require.main === module) {
const ajv = new Ajv({ allErrors: true })
ajvErrors(ajv)
addFormats(ajv)
const validate = ajv.compile(schema)

const data: Array = [
{
actionType: 'UPLOAD',
},
]

if (validate(data)) {
console.log(data)
} else {
console.log(validate.errors)
}
}
```

Run this using `ts-node` or compile and run it via node. The output I get is
```
[
{
instancePath: '/0',
schemaPath: '#/items/anyOf/0/required',
keyword: 'required',
params: { missingProperty: 'url' },
message: "must have required property 'url'"
},
{
instancePath: '/0',
schemaPath: '#/items/anyOf/0/required',
keyword: 'required',
params: { missingProperty: 'filename' },
message: "must have required property 'filename'"
},
{
instancePath: '/0',
schemaPath: '#/items/anyOf/1/required',
keyword: 'required',
params: { missingProperty: 'email' },
message: "must have required property 'email'"
},
{
instancePath: '/0/actionType',
schemaPath: '#/items/anyOf/1/properties/actionType/const',
keyword: 'const',
params: { allowedValue: 'EMAIL' },
message: 'must be equal to constant'
},
{
instancePath: '/0',
schemaPath: '#/items/anyOf',
keyword: 'anyOf',
params: {},
message: 'must match a schema in anyOf'
}
]
```

When I specify `actionType: 'UPLOAD'`, I expect that the only missing fields should `url` and `filename`. The errors output by AJV are confusing and misleading.

In contrast, the typescript type inference engine is correctly able to deduce the the missing fields once the `actionType` field is set to one of `EMAIL` or `UPLOAD`.

Here are my versions via `yarn list`:
```
├─ ajv-errors@3.0.0
├─ ajv-formats@2.1.1
│ └─ ajv@^8.0.0
├─ ajv@8.8.2
│ ├─ fast-deep-equal@^3.1.1
│ ├─ json-schema-traverse@^1.0.0
│ ├─ require-from-string@^2.0.2
│ └─ uri-js@^4.2.2
```

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.