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.transformis used for transformation that never fail!If is possible for a transformation to fail use
Schema.transformOrFailinstead.
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 withParseErrorotherwise) - Schema uses the
decodefunction we defined to convertnumbertostring
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");