sinclairzx81 / typebox

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

No coercion in intersection of unions #787

Closed nicolabovolato closed 5 months ago

nicolabovolato commented 6 months ago

Hi,

I'm using Typebox 0.32.15 and this parse function, it looks like string coercion is not working properly when combining intersections and unions.

import { TSchema, Type } from '@sinclair/typebox';
import { Value } from '@sinclair/typebox/value';

const parse = <T extends TSchema>(T: T, value: unknown) =>
  Value.Decode(T, Value.Clean(T, Value.Default(T, Value.Convert(T, value))));

// OK
console.log(
  '1',
  parse(
    Type.Union([
      Type.Object({
        a: Type.Number(),
      }),
      Type.Object({
        b: Type.Number(),
      }),
    ]),
    { a: '1' }
  )
);
console.log(
  '2',
  parse(
    Type.Intersect([
      Type.Object({
        a: Type.Number(),
      }),
      Type.Object({
        c: Type.Number(),
      }),
    ]),
    { a: '1', c: '3' }
  )
);

// Fails
console.log(
  '3',
  parse(
    Type.Intersect([
      Type.Union([
        Type.Object({
          a: Type.Number(),
        }),
        Type.Object({
          b: Type.Number(),
        }),
      ]),
      Type.Object({
        c: Type.Number(),
      }),
    ]),
    {
      a: '1',
      c: '3',
    }
  )
);
sinclairzx81 commented 6 months ago

@nicolabovolato Hi, Thanks for reporting!

Yes, this is a known limitation with TypeBox's current Convert logic. Looking at the code, I think it needs a review. Will investigate this when I next get some time to dig into the code, however keep in mind, a fix may take some time to implement (as intersection value handling is very complex and has been deferred a few times before, and there is a little bit of cross over with intersection handling elsewhere in the library which I'd like to take a look at also)

Will keep this issue open in the interim. Thanks again!

sinclairzx81 commented 5 months ago

@nicolabovolato Hi!

Hey, have pushed a fix for this on revision 0.32.16. The update should perform the intersected/union conversion, but just be mindful to always check the return value from Convert (as there are many cases where conversion may not be possible). If you experience any issues with the update, feel free to ping on this thread.

Thanks again for reporting! S