Io-ts: Question: How to make a tuple with more than 5 types?

Created on 30 Mar 2020  路  3Comments  路  Source: gcanti/io-ts

If I use t.tuple, it starts to error once I put 6 types. This is my code:
t.tuple([t.number, t.number, t.number, t.number, t.number, t.number, t.any, t.number])

Most helpful comment

You can actually make it work without the as const:

type TupleFn = <TCodecs extends readonly [t.Mixed, ...t.Mixed[]]>(
  codecs: TCodecs,
  name?: string,
) => t.TupleType<
  {
    -readonly [K in keyof TCodecs]: TCodecs[K];
  },
  {
    [K in keyof TCodecs]: TCodecs[K] extends t.Mixed
      ? t.TypeOf<TCodecs[K]>
      : unknown;
  },
  {
    [K in keyof TCodecs]: TCodecs[K] extends t.Mixed
      ? t.OutputOf<TCodecs[K]>
      : unknown;
  }
>;
const tuple: TupleFn = t.tuple as any;

This forces TypeScript to infer TCodecs as a tuple, rather than an array.

All 3 comments

I've submitted a PR that resolves this, but only for TypeScript 3.8+. If you're using TypeScript 3.8, you can workaround this for now via:

type TupleFn = <TCodecs extends readonly t.Mixed[]>(
  codecs: TCodecs,
  name?: string,
) => t.TupleType<
  {
    -readonly [K in keyof TCodecs]: TCodecs[K];
  },
  {
    [K in keyof TCodecs]: TCodecs[K] extends t.Mixed
      ? t.TypeOf<TCodecs[K]>
      : unknown;
  },
  {
    [K in keyof TCodecs]: TCodecs[K] extends t.Mixed
      ? t.OutputOf<TCodecs[K]>
      : unknown;
  }
>;
const tuple: TupleFn = t.tuple as any;

and then use tuple in place of t.tuple.

Forgot to mention, you will also need to mark the input as const e.g.

t.tuple([
  t.number, t.number, t.number, t.number, t.number, t.number, t.any, t.number,
] as const)

You can actually make it work without the as const:

type TupleFn = <TCodecs extends readonly [t.Mixed, ...t.Mixed[]]>(
  codecs: TCodecs,
  name?: string,
) => t.TupleType<
  {
    -readonly [K in keyof TCodecs]: TCodecs[K];
  },
  {
    [K in keyof TCodecs]: TCodecs[K] extends t.Mixed
      ? t.TypeOf<TCodecs[K]>
      : unknown;
  },
  {
    [K in keyof TCodecs]: TCodecs[K] extends t.Mixed
      ? t.OutputOf<TCodecs[K]>
      : unknown;
  }
>;
const tuple: TupleFn = t.tuple as any;

This forces TypeScript to infer TCodecs as a tuple, rather than an array.

Was this page helpful?
0 / 5 - 0 ratings