简体   繁体   中英

io-ts how to use a custom union as type to be checked at run time

I would like to use a custom union, or generally a custom type in io-ts.

I receive an error in this like

T.array(T.type(MyUnion))

Could you please tell me what is the right way to achieve this?

import * as T from 'io-ts';
import * as E from 'fp-ts/Either';
import { pipe } from 'fp-ts/lib/function';

console.clear();

type MyUnion = 'item-a' | 'item-b' | 'item-c';

const test1 = T.type({
  data: T.array(T.string),
});


pipe(test1.decode({ data: ['hello'] }), E.fold(console.error, console.log)); // OK

const test2 = T.type({
  data: T.array(T.type(MyUnion)), // ERROR
});

pipe(test2.decode({ data: ['hello'] }), E.fold(console.error, console.log));

You would need to define a variable named MyUnion so you can use at runtime first:

const MyUnion = T.union([T.literal("item-a"), T.literal("item-b"), T.literal("item-c")]);

but it's quite redundant to use this again:

type MyUnion = 'item-a' | 'item-b' | 'item-c';

Fortunately, io-ts has a built-in type TypeOf that gets the type of an io-ts type as a TS type, which removes the redundancy:

type MyUnion = T.TypeOf<typeof MyUnion>;
//   ^? 'item-a' | 'item-b' | 'item-c'

Then you'll be able to use MyUnion as both an io-ts type (at runtime), and a TS type (at compile-time):

const test2 = T.type({
  data: T.array(MyUnion), // ok
});

Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM