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 withParseError
otherwise) - Schema uses the
decode
function we defined to convertnumber
tostring
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");