# Composing io-ts Codecs

> This post assumes that you know what [io-ts](https://github.com/gcanti/io-ts-types) is. If you want to learn about it I recommend reading [this page](https://github.com/gcanti/io-ts/blob/master/index.md) and [the docs](https://gcanti.github.io/io-ts/).

It is pretty common to want to do something like take a value with an `unknown` type, check that it is a string, check that the string is valid JSON, parse it if it is, and then check that that parsed value has the type that we want. For example we might want to define a function that has the type

```typescript
import * as t from "io-ts";

type unknownToJsonToPerson = (
  value: unknown
) => t.Validation<{ name: string; age: number }>;
```

We could use `io-ts` and `io-ts-types` to fill in the function body like this

```typescript
import * as t from "io-ts";
import { flow } from "fp-ts/function";
import { JsonFromString } from "io-ts-types";
import { chain } from "fp-ts/lib/Either";

const unknownToJsonToPerson: (
  value: unknown
) => t.Validation<{ name: string; age: number }> = flow(
  t.string.decode,
  chain(JsonFromString.decode),
  chain(t.strict({ name: t.string, age: t.number }).decode)
);
```

Which is... OK, but we can do better. Because, in my experience, something one needs to do a lot when using `io-ts` it would be nice if we could have a `compose` function that we could use to compose codecs. We could then use that to do something like

```typescript
import * as t from "io-ts";
import { pipe } from "fp-ts/function";
import { JsonFromString, Json } from "io-ts-types";

const unknownToJsonToPerson = pipe(
  t.string,
  compose(JsonFromString),
  compose<unknown, Json, { name: string; age: number }>(
    t.strict({ name: t.string, age: t.number })
  )
);
```

Handily, I've written that `compose` function and it looks like this!

```typescript
export const compose =
  <I2, A extends I2, B>(Codec2: t.Type<B, A, I2>) =>
  <O1, I1, Name extends string = string>(
    Codec1: t.Type<A, O1, I1>,
    name?: Name
  ): t.Type<B, O1, I1> => {
    return new t.Type<B, O1, I1>(
      name || `${Codec1.name} -> ${Codec2.name}`,
      (u): u is B => Codec2.is(u),
      (a, c) =>
        pipe(
          a,
          (a) => Codec1.validate(a, c),
          chain((b) => Codec2.validate(b, c))
        ),
      (b) =>
        pipe(
          b,
          (b) => Codec2.encode(b),
          (a) => Codec1.encode(a)
        )
    );
  };
```

Un-handily, and as you might have noticed from my usage example, after piping to `compose` once you do have to explicitly define the type of your second invocation. I don't understand why this is the case, but if you can work out a way around this leave a comment explaining how, and ideally explaining why it was a problem in the first place, and I will be very pleased with you.
