Vyhledávání na webu

typescript - Pole bez validace undefined s io-ts


Používáme io-ts pro validaci externích dat z HTTP služeb. Napsal jsem kodek, který vezme jiný kodek C a vrátí Either<t.Errors, C | undefined>, ale ve skutečnosti nikdy nechybuje (jen aby vyhovoval t.Type). Je to proto, že ze služby dostáváme pole různých typů a nové mohou být přidány v budoucnu, takže chceme, aby to pokračovalo v práci, ale jen ignorovalo ty, které jsou undefined. Vypadá to takto:

export function tryDecode<C extends io.Mixed>(
  codec: C,
  onLeft?: (validation: io.Validation<unknown>) => void,
) {
  return new io.Type<io.TypeOf<C> | undefined, io.OutputOf<C>, unknown>(
    'tryDecode',
    (input: unknown): input is C | undefined => {
      return codec.is(input) || input === undefined;
    },
    (u, c) => {
      const validation = codec.validate(u, c);

      return fold(
        () => {
          if (onLeft) {
            onLeft(validation);
          }

          return io.success(undefined as C | undefined);
        },
        (right: C | undefined) => io.success(right),
      )(validation);
    },
    io.identity,
  );
}

Snažím se napsat codec arrayWithoutUndefined, který funguje stejně jako io.array, ale odstraní jakýkoli prvek, který je undefined. Neměl by selhat (pokud to není pole). Můj dosavadní pokus:

export function arrayWithoutUndefined<C extends io.Mixed>(
  codec: C,
  name = `arrayWithoutUndefined<${codec.name}>`,
) {
  const arr = io.array(codec);

  return new io.Type(
    name,
    (u): u is Array<io.TypeOf<C>> => arr.is(u) && !u.includes(undefined),
    (u, c) =>
      either.chain(codec.validate(u, c), as =>
        io.success(as.filter(notUndefined)),
      ),
    arr.encode,
  );
}

notUndefined je pomocník, který zajišťuje (a: A | undefined): a is A => .... Poté bych je použil společně jako const Modules=arrayWithoutUndefined(tryDecode(UnionOfDifferentModules)), ale Modules je stále vyjádřeno jako Array<UnionOfDifferentModules | undefined>, když chci, aby to bylo jen Array<UnionOfDifferentModules>. Je možné to nějak vyjádřit v TypeScript/io-ts? Podíval jsem se na podmíněné typy, ale bohužel nemám ponětí, jak to vyjádřit.

Odpověď č. 1

Tento problém mohl být vyřešen sám v novějších verzích TypeScriptu, které podporují typové záruky v příkazech filter pro pole.

Je také možné, že by zde mohly pomoci explicitní generika pro t.Type.

type Subtract<A, B> = A extends B ? never : A;

return io.Type<Subtract<t.TypeOf<C>, undefined>, unknown[], unknown>(...);