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>(...);
