gcanti / io-ts-types

A collection of codecs and combinators for use with io-ts
https://gcanti.github.io/io-ts-types/
MIT License
311 stars 40 forks source link

How to extract the static type of mapped output? #143

Open fernandomrtnz opened 4 years ago

fernandomrtnz commented 4 years ago
import * as iots from "io-ts";
import * as iotsTypes from "io-ts-types";
import { isRight } from "fp-ts/lib/Either";
import reporter from "io-ts-reporters";

const payload = {
  attributes: {
    description: "desc",
    folderId: "168c3a5e-24c7-467b-8cd6-9324662bcc5e",
    name: "root_folder_1592574328"
  },
  id: "ab1fb10e-a945-4f4d-91d1-b336f8ea7bd9",
  type: "folder-generic"
};

const PayloadCodec = iots.readonly(
  iotsTypes.mapOutput(
    iots.type({
      id: iots.string,
      attributes: iots.type({
        description: iots.string,
        folderId: iots.string,
        name: iots.string
      }),
      type: iots.literal("folder-generic")
    }),
    (o) => ({
      id: o.id,
      type: o.type,
      ...o.attributes
    })
  )
);

// Returns
// {
//   readonly id: string;
//   readonly attributes: {
//       description: string;
//       folderId: string;
//       name: string;
//   };
//   readonly type: "folder";
// }
// but I expected
// {
//   readonly id: string;
//   readonly description: string;
//   readonly folderId: string;
//   readonly name: string;
//   readonly type: "folder";
// }
type Payload = iots.TypeOf<typeof PayloadCodec>;

const decoderResult = PayloadCodec.decode(payload);

if (isRight(decoderResult)) {
  console.log(decoderResult.right);
} else {
  console.log(reporter.report(decoderResult).join("\n"));
}

I expected the Payload type to have the mapped output, but instead I'm receiving the original.

You can play with the example in https://codesandbox.io/s/practical-kalam-9ii7i?file=/src/index.ts.

gcanti commented 4 years ago

@fernandomrtnz with mapOutput you can change the output type (i.e. the O type in Type<A, O, I>), looks like you want to change the A type instead