【问题标题】:Get union codec from type values in io-ts从 io-ts 中的类型值获取联合编解码器
【发布时间】:2022-03-26 12:57:19
【问题描述】:

我正在尝试从 io-ts 中的类型编解码器创建联合编解码器。 我想要实现的基本上是从以下转变:

import * as t from 'io-ts'

const FilterTypeC = t.type({
        POTATO: t.literal('POTATO'),
        CABBAGE: t.literal('CABBAGE'),
        BANANA: t.literal('BANANA'),
        TOMATO: t.literal('TOMATO'),
    });

进入:

const FilterTypeUnionC = t.union([t.literal('POTATO'), t.literal('CABBAGE'), t.literal('BANANA'), t.literal('TOMATO')])

在 io-ts 中有什么好的方法吗?我尝试调整similar typescript example,但没有成功。我会很感激任何提示

【问题讨论】:

    标签: typescript types dynamic-typing


    【解决方案1】:

    如果我正确理解您要查找的内容,您已经有一个 TypeC 编解码器,并且正在尝试创建一个新编解码器来检查该基本编解码器的可能值的联合?您正在寻找的 TypeScript 类型会是这样的吗?

    type valuesOfCodec<T> = t.Type<T[keyof T>, T[keyof T], unknown>;
    

    编解码器将在哪里解码给定接口的值。

    我认为io-ts 不支持开箱即用,但我能够编写一个快速函数来创建一个给定TypeC 的编解码器。

    
    // This helper is needed because `t.union` expects at least two codecs
    function hasAtLeastTwoItems<T>(t: T[]): t is [T, T, ...T[]] {
      return t.length > 1;
    }
    
    // This is the main helper which pulls the value codecs out of a t.TypeC
    function valuesOf<T extends t.Props>(
      type: t.TypeC<T>
    ): t.Type<t.TypeOfProps<T>[keyof T], t.TypeOfProps<T>[keyof T], unknown> {
      const valueCodecs: t.Mixed[] = [];
    
      for (const key of Object.keys(type.props)) {
        // Grab all of the value codecs out of the iterable properties of the
        // input type's `props` field.
        valueCodecs.push(type.props[key]);
      }
    
      // If the original type has at least two fields, we can make a union
      // out of the values.
      if (hasAtLeastTwoItems(valueCodecs)) {
        return t.union(valueCodecs);
      }
      // If the type has one field, then the value codec will just be that
      // fields codec.
      if (isNonEmpty(valueCodecs)) {
        return valueCodecs[0];
      }
    
      // If the type has no fields, then we shouldn't really be decoding
      // successfully at all so I just threw together this `t.Type` that
      // never succeeds at decoding.
      return new t.Type<unknown, unknown, unknown>(
        "always fail",
        (x): x is unknown => false,
        (i, c) => t.failure(i, c, "Cannot decode this codec"),
        (i) => i
      );
    }
    
    const FilterUnionTypeC = valuesOf(FilterTypeC);
    console.log(FilterUnionTypeC.decode("POTATO")); // -> Right<...>
    

    这应该可以解决问题,但我会稍微警告一下,这依赖于 t.TypeC 类中存在的特殊元数据,因此即使 A 类型是记录/接口,这也不适用于其他编解码器.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-07
      • 2019-04-20
      • 2019-08-27
      • 2022-07-19
      • 1970-01-01
      • 2019-03-05
      相关资源
      最近更新 更多