arktypea
arktype9mo ago
Flosi21

Discriminated union with union type discriminator gives wrong error messages

Let's say I have this type, right here:

const Thing = type.or({
    option: "'A' | 'B'",
    a: "string"
}, {
    option: "'C' | 'D'",
    b: "string"
}, {
    option: "'E'",
    c: "string"
})

const out = Thing({
    option: 'A'
})


This will produce the error message a must be a string (was missing), b must be a string (was missing) or c must be a string (was missing), however what one would expect is a must be a string (was missing)

Now interestingly this only occurs because when more then ONE of the discriminators is a union. This type here will produce the correct error message a must be a string (was missing)
const Thing = type.or({
    option: "'A' | 'B'",
    a: "string"
}, {
    option: "'C'",
    b: "string"
}, {
    option: "'E'",
    c: "string"
})

const out = Thing({
    option: 'A'
})

The why becomes apparent when we take a look at the precompilation, in case 2 it can just switch case over the options

union329Allows(data, ctx) {     switch(data?.option) {
            case "C": return this.intersection2241Allows(data)
            case "E": return this.intersection2247Allows(data)
            default: return this.intersection1938Allows(data)
        }
        return false
     },


where in case 1 it uses the intersectionAllows which cannot tell, that when option = "A" the only remaining field to validate will be a because it checks the WHOLE data instead of just looking at the option and then "locking" in.

union298Allows(data, ctx) {     if (this.intersection1938Allows(data)) {
            return true
        }
        if (this.intersection1941Allows(data)) {
            return true
        }
        if (this.intersection1944Allows(data)) {
            return true
        }
        return false
     },


Is this a bug? Is there some part of set theory that can justify this behaviour that i do not yet understand? 😅
Was this page helpful?