export interface Codec<I, O, A> extends D.Decoder<I, A>, E.Encoder<O, A> {}
A codec is just a decoder and an encoder packed together.
The following laws must hold
pipe(codec.decode(u), E.fold(() => u, codec.encode)) = u
for allu
inunknown
codec.decode(codec.encode(a)) = E.right(a)
for alla
inA
You can build a new codec using the make
helper
Example
import * as C from 'io-ts/Codec'
import * as D from 'io-ts/Decoder'
import * as E from 'io-ts/Encoder'
import { pipe } from 'fp-ts/function'
const decoder: D.Decoder<unknown, number> = pipe(
D.string,
D.parse((s) => {
const n = parseFloat(s)
return isNaN(n)
? D.failure(s, `cannot decode ${JSON.stringify(s)}, should be parsable into a number`)
: D.success(n)
})
)
const encoder: E.Encoder<string, unknown> = {
encode: String
}
export const NumberFromString: C.Codec<unknown, string, number> = C.make(decoder, encoder)