sinclairzx81 / typebox

Json Schema Type Builder with Static Type Resolution for TypeScript
Other
4.77k stars 152 forks source link

Support for discriminator #760

Closed Baptiste-Garcin closed 6 months ago

Baptiste-Garcin commented 6 months ago

Hi there !

I haven't found any information about a possible support for discriminator in Union types although it is now supported by AJV.

Did I miss something ? I understand that it's OpenAPI feature and not a JSON schema one but do you think, it's a possible evolution for TypeBox ?

Cheers

sinclairzx81 commented 6 months ago

@Baptiste-Garcin Hi,

TypeBox won't support a DiscrimatedUnion type because it's not part of the Json Schema specification. Ajv does provide support for it, but it needs to be enabled to use (and it's still outside the specification). Note also that TypeScript doesn't have a representation of DiscriminatedUnion either. As it has a structural type system, it has features to deduce a union variant through control flow checks.

TypeScript Link Here

import { Type, Static } from '@sinclair/typebox'

const A = Type.Object({
   type: Type.Literal('A'), // Discriminator
   value: Type.Number()
})
const B = Type.Object({
   type: Type.Literal('B'), // Discriminator
   value: Type.String()
})
const C = Type.Object({
   type: Type.Literal('C'), // Discriminator
   value: Type.Boolean()
})

const U = Type.Union([A, B, C])

function test(union: Static<typeof U>) {
    if(union.type === 'B') {  // <- Control Flow Check

        union.value           // <- Value is String
    }
}

If you need to represent a property in the schematic that indicates "which" property of the union variants should be used for discrimination, you can optionally add this metadata in with.

const U = Type.Union([A, B, C], { discriminator: 'type' })

However, this is not required for validation (it's only usually helpful for tools that might transform a schema into code for nominal type systems). As far as Json Schema goes, the discriminator is implicit by having a unique discriminator field on each union variant.

Will close off this issue for now as this functionality is largely out of scope. Cheers S