Creating a custom Union Transformation in TypeScript using the Effect library involves a few step...

I’m trying to build a custom Union Transformation. My aim is to convert from and to a custom data type called IndexType. This type represents a pointer to the original type. Any tips or hints you can share would be super helpful!
const IndexType = Schema.Struct({
  index: Schema.Number,
});

const MyUnion = <Members extends ReadonlyArray<Schema.Schema.Any>>(
  ...members: Members
) =>
  Schema.transformOrFail(IndexType, Schema.Union(...members), {
    strict: true,
    encode: (value, toA) => {
      const index = members.findIndex((member) => Schema.is(member, value));
      return ParseResult.succeed({
        index,
      });
    },
    decode: (value) => {
      const index = Number(value.index);
      if (index < 0 || index >= members.length) {
        throw new Error("Invalid index");
      }
      return ParseResult.decode(members[index])(value);
    },
  });

const schema = MyUnion(
  Schema.Struct({
    a: Schema.String,
  }),
  Schema.Struct({
    b: Schema.String,
  }),
  Schema.Struct({
    c: Schema.String,
  })
);

const dataA = {
  a: "hello",
};

const dataB = {
  b: "world",
};

const dataC = {
  c: "!",
};

const encoded = Schema.encodeUnknownSync(schema)(dataB);
//should return { index: 1 } , but it returns { index: 0 }
console.log(encoded);
const decoded = Schema.decodeUnknownSync(schema)(encoded);
// should return { b: "world" }, but it fails with an error
// ParseError: ({ readonly index: number } <-> { readonly a: string } | { readonly b: string } | { readonly c: string })
// └─ Transformation process failure
//    └─ { readonly a: string }
//       └─ ["a"]
//          └─ is missing

also typescript complains about MyUnion Schema having the Context as unknown
 Types of property 'Context' are incompatible.
    Type 'unknown' is not assignable to type 'never'.ts(2345)
Was this page helpful?