effect-app / libs

The core libraries to build apps with Effect
44 stars 6 forks source link

Field info support unions #70

Closed jfet97 closed 7 months ago

jfet97 commented 7 months ago

The PR

Ok this was hard but I reached a point where I'm satisfied with my work, so I'm gonna open a PR.

The main achievement is the support for unions, expecially when it comes to tagged unions that use _tag as discriminant:

class Circle extends S.TaggedClass<Circle>()("Circle", {
  radius: S.PositiveInt
}) {}

class Square extends S.TaggedClass<Square>()("Square", {
  sideLength: S.PositiveInt
}) {}

class Triangle extends S.TaggedClass<Triangle>()("Triangle", {
  base: S.PositiveInt,
  height: S.number
}) {}

export class ShapeContainer extends S.Class<ShapeContainer>()({
  shape: S.union(Circle, Square, Triangle)
}) {}

const fieldInfo = buildFieldInfoFromFields(ShapeContainer)

// this array contains the field infos for the 3 possible shapes
const shapeInfos = fieldInfos.fields.shape.members

shapeInfos.forEach((i) => {
  // the _tag has been propagated in ___tag so that we can narrow the info i
  expect(["Circle", "Square", "Triangle"]).toContain(i.___tag)

  switch (i._infoTag) {
    case "Circle":
      i.fields._tag // FieldInfo<"Circle">
      i.fields.radius // FieldInfo<number & S.PositiveIntBrand>
      break
    case "Square":
      i.fields._tag // FieldInfo<"Square">
      i.fields.sideLength // FieldInfo<number & S.PositiveIntBrand>
      break
    case "Triangle":
      i.fields._tag // FieldInfo<"Triangle">
      i.fields.base // FieldInfo<number & S.PositiveIntBrand>
      i.fields.height // FieldInfo<number>
      break
  }
})

The propagation of the _tag into _infoTag will be convinient for the frontend when it comes to select the right field infos provider for properties that are discriminated unions of schemas.

Remarks

I'm not sure if how I handled schemas that contains schema classes is the right way to do so, internally those classes became transformations instead of type literals. Please check in handlePropertySignature