ianstormtaylor/superstruct

Describe does not work well with union types

BoveFabio opened this issue · 2 comments

Hi everyone,

I stumbled across a seemingly simple example where Describe does not work well with union. However, it might be I am missing something.

Consider the following:

type A = {
    a: "a";
};
type B = {
    b: "b";
};

const aStruct: Describe<A> = object({
    a: literal("a"),
});
const bStruct: Describe<B> = object({
    b: literal("b"),
});
const aorbStruct: Describe<A | B> = union([aStruct, bStruct]);

I would expect this to work. However, aorbStruct shows a TS error:

TS2322: Type Struct<A | B, null> is not assignable to type Describe<A | B>
  Types of property schema are incompatible. 
    Type null is not assignable to type
      {
        a: Describe<"a">; 
      } | {
        b: Describe<"b">;
      }

The strange thing is that it works once I include a primitive in the union:

const AorBorNumberStruct: Describe<A | B | number> = union([aStruct, bStruct, number()]);

works fine.

Could you please

  • either help me out and show me how to get the const aorbStruct: Describe<A | B> = union([aStruct, bStruct]); case working
  • or confirm that this is bug?

Thank you!

Same here, any news on the subject?

Node: v20.16.0
SuperStruct: v2.0.2

I don't know if this is part of the same issue, but it seems like unions fail with partial():

https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbzgQylZBPANHMqbDIA2OAdgK5FHIBGRApjhDQFb0DGMOAzjFMKQDmOcqWARScAL5wAZlAgg4AIm7kw9KLyjlOygNwAoUJFhwYGDYjgARet3b8a9aXIVLV6zdt0wDh41IYTVlkdhcAFURDOFi5CAgALjhtAUE4AB8UvjSAbQBdTLgKKiMpAPYJXnMANWJgABNkAglkuwcnegAeCIA+OABeOGY2TgAKBBi42QTkkuo6ejHRcVIx3NShMYBKHFR0DDHNwR3t-O3dwylto0NK0mq8WEIiCLqiRubVtvtHYGcugAFfAvHq9fpDJ4EYhjGDvT4tUg3IA

I have a gut feeling this is because any expansion of a union needs to be simplified, something like Describe<OriginalUnion> | Describe<undefined> => Describe<OriginalUnion | undefined> ?