ajv-validator / ajv-validator/ajv

Conditional type + union + generics not allowed

Abierto
#2,172 0 comentarios 1 reacción 0 asignados Ver en GitHub
limitation typescript
Lenguaje dominante
TypeScript
Estrellas
14.8k
Forks
1k
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

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

**Ajv options object**
Using these:
```
import ajvErrors from 'ajv-errors'
import addFormats from 'ajv-formats'
import betterAjvErrors from 'better-ajv-errors'
```

default options.

**Problem**

I want to have a type definition like

```typescript
type Test2 = T extends undefined ? undefined : JSONSchemaType
```

However, this fails for types where `T` is a union type. Here is a complete example highlighting the problem:

```typescript
import { JSONSchemaType } from 'ajv'

type ExampleStringBody = {
foo: string
}

type ExampleNumberBody = {
bar: number
}

type ExampleBody = ExampleStringBody | ExampleNumberBody

const exampleNumberBodySchema: JSONSchemaType = {
type: 'object',
required: ['bar'],
properties: {
bar: {
type: 'number',
},
},
}

const exampleStringBodySchema: JSONSchemaType = {
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'string',
},
},
}

const exampleBodySchema: JSONSchemaType = {
type: 'object',
oneOf: [exampleNumberBodySchema, exampleStringBodySchema],
}

// This one does not work. The rest of the example below this one work.
// ✕ | ✓ conditional type | ✓ union | ✓ generic
type Type1 = T extends undefined ? undefined : JSONSchemaType
const a: Type1 = exampleBodySchema

// ✓ | ✓ conditional type | ✕ union | ✓ generic
const b: Type1 = exampleStringBodySchema

// ✓ | ✕ conditional type | ✓ union | ✓ generic
type Type2 = JSONSchemaType
const c: Type2 = exampleBodySchema

// ✓ | ✓ conditional type | ✓ union | ✕ generic
type Test1 = ExampleBody extends undefined
? undefined
: JSONSchemaType
const d: Test1 = exampleBodySchema

// ✓ | ✕ conditional type | ✕ union | ✓ generic
const e: Type2 = exampleBodySchema

// ✓ | ✓ conditional type | ✕ union | ✕ generic
type Type3 = ExampleStringBody extends undefined
? undefined
: JSONSchemaType
const f: Type3 = exampleStringBodySchema
```

For whatever reason, the specific combination of generics + union + generics is not accepted by typescript. The error I get out is:

```
const a: UncheckedJSONSchemaType | UncheckedJSONSchemaType

Type '{ oneOf: readonly UncheckedJSONSchemaType[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<...> | undefined; definitions?: Record<...> | undefined; }' is not assignable to type 'UncheckedJSONSchemaType | UncheckedJSONSchemaType'.
Type '{ oneOf: readonly UncheckedJSONSchemaType[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<...> | undefined; definitions?: Record<...> | undefined; }' is not assignable to type '{ type: "object"; additionalProperties?: boolean | UncheckedJSONSchemaType | undefined; unevaluatedProperties?: boolean | UncheckedJSONSchemaType | undefined; ... 7 more ...; maxProperties?: number | undefined; } & { ...; } & { ...; } & { ...; }'.
Property 'type' is missing in type '{ oneOf: readonly UncheckedJSONSchemaType[]; } & { [keyword: string]: any; $id?: string | undefined; $ref?: string | undefined; $defs?: Record<...> | undefined; definitions?: Record<...> | undefined; }' but required in type '{ type: "object"; additionalProperties?: boolean | UncheckedJSONSchemaType | undefined; unevaluatedProperties?: boolean | UncheckedJSONSchemaType | undefined; ... 7 more ...; maxProperties?: number | undefined; }'.ts(2322)
json-schema.d.ts(57, 5): 'type' is declared here.
```

I've ready all of the threads on union types in here that I can find.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.