unsplash/sum-types

Serialize nested values

Closed this issue · 1 comments

Consider this sum type which has another sum type nested inside of it. When we call Sum.serialize, only the outer sum type is serialized. The nested sum type is not serialized.

import * as Sum from "@unsplash/sum-types";
import { pipe } from "fp-ts/lib/function";

type Inner = Sum.Member<"Foo"> | Sum.Member<"Bar">;
type Outer = Sum.Member<"A"> | Sum.Member<"B", Inner>;

const Outer = Sum.create<Outer>();

declare const outer: Outer;

const serialized = pipe(outer, Sum.serialize);
//    ^? const serialized: readonly ["A", null] | readonly ["B", Inner]

Likewise, consider this sum type which has a Date inside of it. When we call Sum.serialize, only the outer sum type is serialized. The Date inside is not serialized.

import * as Sum from "@unsplash/sum-types";
import { pipe } from "fp-ts/lib/function";

type MySum = Sum.Member<"A"> | Sum.Member<"B", Date>;

const MySum = Sum.create<MySum>();

declare const mySum: MySum;

const serialized = pipe(mySum, Sum.serialize);
//    ^? const serialized: readonly ["A", null] | readonly ["B", Date]

How should we handle situations like this?

Perhaps we need an API like this:

const serialized = pipe(
  mySum,
  Sum.serialize({
    B: serializeDate
  })
);
const deserialized = pipe(
  serialized,
  Sum.deserialize<MySum>({
    B: deserializeDate
  })
);
samhh commented

Serialisation from within the core library is very thin and really only serves to remove the Symbol wrappers from our keys. The expectation is that, given that serialisation is such a large area of concern, this is then handed off to something like io-ts, as in our bindings.