nvie/decoders

Union type is not inferred correctly from either decoder

vjrasane opened this issue · 1 comments

Either decoders signature does not seem to infer types correctly from the input decoders:

import { object, string, either } from "decoders";

const UnionDecoder = either(
    object({
        /* dependent fields */
        dependency: string,
        dependant: string,
        /* common fields */
        common: string
    }),
    object({
        common: string
    })
)

type UnionDecoderType = DecoderType<typeof UnionDecoder>
/**
 * { common: string; }
 */

 /* this is not assignable */
 const decoderTypeValue: UnionDecoderType = {
     dependency: "this does not compile",
     dependant: "value",
     common: "hello"
}

the use case here is that some of the fields have to be defined together, so they cannot be simply optional

I'm not sure what exactly is wrong with the type signature, but I've had a similar pattern in a personal project and found that the following signature yields correct type:

import { Decoder, DecoderType, object, string } from "decoders";

const either = <A extends Array<Decoder<DecoderType<A[number]>>>>(
    ...arr: A
): Decoder<DecoderType<A[number]>> => {
    throw Error("implementation")
}

const UnionDecoder = either(
    object({
        /* dependent fields */
        dependency: string,
        dependant: string,
        /* common fields */
        common: string
    }),
    object({
        common: string
    })
)

type UnionDecoderType = DecoderType<typeof UnionDecoder>
/*
    {
        dependency: string;
        dependant: string;
        common: string;
    } | {
        common: string;
    }
 */

/* now this is assignable */
const decoderTypeValue: UnionDecoderType = {
    dependency: "this does compile",
    dependant: "value",
    common: "hello"
}

/* and this is not assignable */
const decoderTypeValue2: UnionDecoderType = {
    dependency: "this does not compile",
    dependant: "value"
}

the signature can of course be cleaned up and extracted to utility types for readability, but that's the gist of it.

Tested with versions:

    "decoders": "^2.0.1",
    "typescript": "^4.9.4"
nvie commented

Hi @vjrasane — this indeed looks like a bug! I'll take a look at this soon (probably somewhere next week at the earliest) to figure out what's wrong here. Thanks for reporting! 🙏