If you have a TUnion<TRef<TObject>[]> and attempt to cast a value into the union, even if it has a matching union discriminator field, it will cast to the wrong union.
import { Type } from "@sinclair/typebox";
import { Cast, Check } from "@sinclair/typebox/value";
const A = Type.Object(
{
type: Type.Literal("a"),
},
{ $id: "a" },
);
const B = Type.Object(
{
type: Type.Literal("b"),
value: Type.Number(),
},
{ $id: "b" },
);
const b = { type: "b" };
const URefs = Type.Union([Type.Ref(A), Type.Ref(B)]);
const failCast = Cast(URefs, [A, B], b); // Ends up casting to A instead of B
console.log("cast with refs", Check(B, failCast));
const U = Type.Union([A, B]);
const successCast = Cast(U, b); // Cast correctly to B
console.log("cast without refs", Check(B, successCast));
The ScoreUnion function only checks the properties of the schema if it is an TObject schema, and since its a TRef it instead just checks if its correct. Presumably it should first check if its a TRef and attempt to Deref it, and failing that move onto the other steps.
If you have a
TUnion<TRef<TObject>[]>
and attempt to cast a value into the union, even if it has a matching union discriminator field, it will cast to the wrong union.The
ScoreUnion
function only checks the properties of the schema if it is anTObject
schema, and since its aTRef
it instead just checks if its correct. Presumably it should first check if its aTRef
and attempt toDeref
it, and failing that move onto the other steps.