具有互斥属性的解码器

Decoder with mutually exclusive properties

使用Decoder API,有没有办法定义具有互斥属性的解码器?

import * as D from 'io-ts/Decoder';

const decoder = pipe(
  D.struct({
    a: D.string
  }),
  D.intersect(
    D.partial({
      b: D.string,
      c: D.boolean
    })
  )
);

以上设置了 bc 都可以存在但可选的情况。我怎么能改为要求 bc 必须 之一,而不是两者都存在?

您可以使用 Union combinator.

const decoder = pipe(
  D.struct({
    a: D.string
  }),
  D.intersect(
    D.union(
      D.struct({ b: D.string }),
      D.struct({ c: D.string })
    )
  )
);

请记住,如果不首先检查这些属性是否存在,您将无法访问 bc,因为 Typescript 无法知道是哪一个你的对象中有两个。

type Decoder = D.TypeOf<typeof decoder>
declare const myDecoder: Decoder;

myDecoder.a // inferred as `string`
myDecoder.b // TYPE ERROR: Property 'b' does not exist on type '{ a: string; } & { c: string; }'
myDecoder.c // TYPE ERROR: Property 'c' does not exist on type '{ a: string; } & { b: string; }'

if ("b" in myDecoder) {
  myDecoder.b // inferred as `string`
}

if ("c" in myDecoder) {
  myDecoder.c // inferred as `string`
}

请注意,在检查两个互斥属性时,您是如何收到类型错误的。 TypeScript 正确地推断出这种情况永远不会发生(myDecoderif 块中被推断为 never

if ("b" in myDecoder && "c" in myDecoder) {
  myDecoder.b // TYPE ERROR: Property 'b' does not exist on type 'never'.
  myDecoder.c // TYPE ERROR: Property 'c' does not exist on type 'never'.
}