Schema type transformations

Using Schema we can apply transformations to base types.

For example we can transform height from a number to a formatted string. We achieve this by using Schema.transform:

const HeightFormat = Schema.Number.pipe(
  Schema.transform(
    Schema.String, // 👈 Transform to a `string`
    {
      decode: (from) => `${from}cm`,
      encode: (to) => Number(to.substring(0, to.length - 2)),
    }
  )
);

export class Pokemon extends Schema.Class<Pokemon>("Pokemon")({
  id: Schema.Number,
  order: Schema.Number,
  name: Schema.String,
  height: HeightFormat,
  weight: Schema.Number,
}) {}

Schema.transform is used for transformation that never fail!

If is possible for a transformation to fail use Schema.transformOrFail instead.

Different encoded and decoded types

Transforming a schema makes the input type (number) different from the output (string).

Since Schema supports both encoding and decoding, we can access the shape of the encoded and decoded Schema using .Encoded and .Type:

const HeightFormat = Schema.Number.pipe(
  Schema.transform(Schema.String, {
    decode: (from) => `${from}cm`,
    encode: (to) => Number(to.substring(0, to.length - 2)),
  })
);

type Encoded = typeof HeightFormat.Encoded; // 👈 `number`
type Decoded = typeof HeightFormat.Type; // 👈 `string`

Using Schema.decode with HeightFormat now works as follows:

  • Schema expects the original type to be number (fail with ParseError otherwise)
  • Schema uses the decode function we defined to convert number to string
const HeightFormat = Schema.Number.pipe(
  Schema.transform(Schema.String, {
    decode: (from) => `${from}cm`,
    encode: (to) => Number(to.substring(0, to.length - 2)),
  })
);

// 👇 Effect<string, ParseError>
const heightFormat = Schema.decode(HeightFormat)(175);

Using Schema.encode we can also convert back from string to number:

const HeightFormat = Schema.Number.pipe(
  Schema.transform(Schema.String, {
    decode: (from) => `${from}cm`,
    encode: (to) => Number(to.substring(0, to.length - 2)),
  })
);

// 👇 Effect<number, ParseError>
const backToNumber = Schema.encode(HeightFormat)("175cm");