Effect CommunityEC
Effect Community2mo ago
4 replies
mechanical_monk

Decoding JSON Objects into Tagged Union Types with Effect Typescript

I have JSON objects coming via HTTP in the shape { attribute: string, op: string, value?: any } and i want to decode them into something like this:
const EqOp = Schema.TaggedStruct("eq", { value: Schema.Any });
const LtOp = Schema.TaggedStruct("lt", { value: Schema.Number }); // operator 'lt' requires a number....
const StartsWithOp = Schema.TaggedStruct("startsWith", { value: Schema.String }); // operator 'startsWith' requires a string...
const ExistsOp = Schema.TaggedStruct("exists", {}); // operator 'exists' doesn't take a value...
// ...etc.

const Op = Schema.Union(EqOp, LtOp, StartsWithOp, ExistsOp, /* ...etc. */);

class Condition extends Schema.Class<Condition>("Condition")({
  attribute: Attribute, // basically string + filters...
  op: Op
}) {}

so that I can then use Match.type<Op>().pipe(Match.tagsExhaustive(...) on the op field.

I'm struggling to find a good way to compose intermediary schemas to end up with this. Ideally I don't want a transform with a big manual switch. I figured out I can do this with Schema.rename to automatically parse the operators correctly into the union variants:
const Base = Schema.Struct({ op: Schema.String, value: Schema.optional(Schema.Any) }).pipe(
    Schema.rename({ op: "_tag" }),
);
const BaseToOp = Base.pipe(Schema.compose(Op))

but I don't know how to get the attribute through this too in a good way. Any advice appreciated!
Was this page helpful?