#javascript #typescript #fp-ts
Вопрос:
В настоящее время я работаю над проектом, в котором есть стек fp-ts и io-ts. Я пытаюсь проверить все ответы, которые мы получаем от бэкенда io-ts
. Я узнал io-ts
, что нет простого способа сделать optional
тип typescript
. И из этой проблемы я нашел обходной путь, чтобы сделать объект с необязательными полями.
Я хочу создать тип, который выглядит примерно так.
type finalType = {
req: string;
opt?: string;
};
В нашем проекте у нас есть эта runDecoder
функция, которая проверяет данные ответов с io-ts
помощью типов. Он прекрасно работает с обычными io-ts
типами, которые не являются необязательными.
Но проблема возникает при проверке, когда он пытается проверить тип, который был сделан необязательным с помощью этого t.intersection
типа. Вот код с примером
import * as Either from "fp-ts/lib/Either";
import * as io from "io-ts";
export const runDecoder = <T extends io.Props>(type: io.TypeC<T>) => (
data: unknown
) => {
const result = type.decode(data);
if (Either.isLeft(result)) {
return Error("error");
}
return result.right;
};
// I want to create type something like this
// type finalType = {
// req: string;
// opt?: string;
// };
const OptionType = io.partial({
opt: io.string
});
const RequiredType = io.type({
req: io.string
});
const FinalType = io.intersection([RequiredType, OptionType]);
type resultType = io.TypeOf<typeof FinalType>;
const respose:resultType = {
req: "str"
};
const decoded = runDecoder(FinalType)(respose);
Ошибка, которую я получаю, заключается в том, что
Argument of type 'IntersectionC<[TypeC<{ req: StringC; }>, PartialC<{ opt: StringC; }>]>' is not assignable to parameter of type 'TypeC<Props>'.
Property 'props' is missing in type 'IntersectionC<[TypeC<{ req: StringC; }>, PartialC<{ opt: StringC; }>]>' but required in type 'TypeC<Props>'.
Я пытался понять ошибку, но я не могу понять, что здесь не так с runDecoder
методом. Вот ссылка на Codesandbox.
Любая помощь будет очень признательна.
Ответ №1:
FinalType
это a IntersectionType
, тогда runDecoder
как принимает a TypeC
.
Type<A, O, I>
├ InterfaceType<P, A, O, I> ( readonly props: P)
│ └ TypeC<P extends Props>
└ IntersectionType<CS, A, O, I> ( readonly types: CS)
Я еще не использовал io-ts, но мне кажется InterfaceType
, что класс (и, следовательно TypeC
, интерфейс, который его расширяет) предназначен только для кодеков для простого типа объектов (например {req: string; opt?: string}
), а не для типов пересечений (например {req: string} amp; {opt?: string}
). Даже несмотря на то, что эти типы в TypeScript могут быть семантически эквивалентны, они не представлены одинаково в io-ts.
Ошибка, которую вы получаете, связана с FinalType
отсутствием props
свойства, требуемого в InterfaceType
because FinalType
is an IntersectionType
.
Я бы сделал runDecoder
так, чтобы принять просто a Type
или даже a Decoder
(что Type
распространяется):
// I: input type
// A: output type
export const runDecoder = <I, A>(type: io.Decoder<I, A>) => (
data: I
): A | Error => {
// ...
}
Комментарии:
1. большое вам спасибо за объяснение ошибки и решение. Теперь это имеет для меня смысл!