import * as t from 'io-ts'; import { Compute, ValueOf } from './type-helpers'; /** * Why does this wrapper exist? * * `io-ts` is awesome and super powerful, but the API leaves some things to be * desired. It was designed to be used with `fp-ts` which is a library for * functional programming patterns in TypeScipt. The resulting type on the * "decode" method is an Either which is great to work with when using `fp-ts`, * but is otherwise cumbersome. * * By introducing an `assert` method, we can guarantee the function will always * return the decoded type by throwing an error if it fails to decode. With * promises we can easily chain an assertion and the promise will reject if * the data fails to decode. * * The other main thing this wrapper seeks to address is the clunkiness of * defining objects. * * If you want to declare an object in io-ts, it looks like this: * * const person = t.type({ firstName: t.string, lastName: t.string }) * * 'type' here is not obvious that it is representing an object, but that's * not the only issue. If you want to make one of the keys optional, you must * manually union the type with t.undefined. * * const person = t.type({ * firstName: t.string, * lastName: t.union([t.string, t.undefined]) * }) * * This isn't so bad that it warrants a wrapper, but it could be improved * upon. The real pain is that when deriving types from this, the 'optional' * key isn't actually optional. * * // { firstName: string, lastName: string | undefined } * type Person = t.TypeOf * * Note that lastName does *NOT* have a question mark after it marking it as * optional. If you wanted to now declare a variable with this type, you MUST * provide the lastName key, even if the value is undefined. * * const p: Person = { firstName: "Kevin", lastName: undefined } * * This is where things get really clunky. The solution according to the docs * is to separate your optional keys (with t.partial) from your required keys * and then intersect the two types together. * * const person = t.intersection([ * t.type({ * firstName: t.string, * }), * t.partial({ * lastName: t.string * }) * ]) * * // Now this is correct * // { firstName: string, lastName?: string | undefined } * type Person = t.TypeOf * * This wrapper provides a much nicer API for this *very* common scenario * addressing the aforementioned quirks of io-ts. * * const person = eg.object({ * firstName: eg.string * lastName: eg.string.optional * }) * * // { firstName: string, lastName?: string | undefined } * type Person = TypeFromCodec * * The `optional` property unions the codec with the `undefined` codec, and the * type information that is derived handles this automatically. */ declare type KeysWithValueType = { [Key in keyof O]: Key; }[Exclude>]; declare type KeysWithoutValueType = { [Key in keyof O]: T extends O[Key] ? never : Key; }[keyof O]; declare type RepackKeys = { [Key in keyof T]: T[Key]; } & {}; declare type EnableOptionalKeys = RepackKeys<{ [MandatoryKey in KeysWithoutValueType]: T[MandatoryKey]; } & { [OptionalKey in KeysWithValueType]?: T[OptionalKey]; }>; export declare class EnGardeAssertionError extends Error { errors: t.Errors; constructor(errors: t.Errors); } declare type IoTsCodec = t.Any; export declare class Codec extends t.Type, t.OutputOf, t.InputOf> { constructor(ioTsCodec: C); assertDecode: (value: unknown) => t.TypeOf; get optional(): Codec>; } export declare class ObjectCodec

extends t.InterfaceType; }>, EnableOptionalKeys<{ [K in keyof P]: t.OutputOf; }>, unknown> { constructor(ioTsCodec: t.TypeC

); assertDecode: (value: unknown) => { [Key in keyof ({ [MandatoryKey in KeysWithoutValueType<{ [K in keyof P]: t.TypeOf; }, undefined>]: { [K in keyof P]: t.TypeOf; }[MandatoryKey]; } & { [OptionalKey in KeysWithValueType<{ [K in keyof P]: t.TypeOf; }, undefined>]?: { [K in keyof P]: t.TypeOf; }[OptionalKey] | undefined; })]: ({ [MandatoryKey in KeysWithoutValueType<{ [K in keyof P]: t.TypeOf; }, undefined>]: { [K in keyof P]: t.TypeOf; }[MandatoryKey]; } & { [OptionalKey in KeysWithValueType<{ [K in keyof P]: t.TypeOf; }, undefined>]?: { [K in keyof P]: t.TypeOf; }[OptionalKey] | undefined; })[Key]; }; create: (value: TypeFromCodec) => { [Key in keyof ({ [MandatoryKey in KeysWithoutValueType<{ [K in keyof P]: t.TypeOf; }, undefined>]: { [K in keyof P]: t.TypeOf; }[MandatoryKey]; } & { [OptionalKey in KeysWithValueType<{ [K in keyof P]: t.TypeOf; }, undefined>]?: { [K in keyof P]: t.TypeOf; }[OptionalKey] | undefined; })]: ({ [MandatoryKey in KeysWithoutValueType<{ [K in keyof P]: t.TypeOf; }, undefined>]: { [K in keyof P]: t.TypeOf; }[MandatoryKey]; } & { [OptionalKey in KeysWithValueType<{ [K in keyof P]: t.TypeOf; }, undefined>]?: { [K in keyof P]: t.TypeOf; }[OptionalKey] | undefined; })[Key]; }; get optional(): Codec>; } export declare type TypeFromCodec = t.TypeOf; export declare const eg: { /** * Picks a subset of ObjectCodec and returns new ObjectCodec. The subset is determined by keys array. * * @param codec Codec to pick from * @param keys Keys to pick * @returns Subset codec that only has 'keys'. */ pick: , Keys extends keyof C["props"]>(codec: C, keys: Keys[]) => ObjectCodec<{ [key in Keys]: C["props"][key]; }>; /** * Omits a subset of ObjectCodec and returns new ObjectCodec. The subset is determined by keys array. * * @param codec Codec to omit from * @param keys Keys to omit * @returns Subset codec without 'keys'. */ omit: , Keys_1 extends keyof C_1["props"]>(codec: C_1, keys: Keys_1[]) => ObjectCodec>>; /** * Creates union-of-literals LiteralType codec from ObjectCodec. * * @param Object codec * @returns LiteralType of keys, where keys are keyof codec. */ keyOf: >(codec: C_2) => Codec>>; emptyArray: Codec>; object:

(p: P, name?: string | undefined) => ObjectCodec

; tuple: (codecs: Codecs, name?: string | undefined) => Codec>; intersection: (codecs: Codecs_1, name?: string | undefined) => Codec>; recursion: (name: string, definition: (self: t.Type) => t.Type) => Codec, A, O, I>>; brand: >(name: Name, base: BaseCodec, predicate: (value: TypeFromCodec) => boolean) => Codec>; enum: (e: Enum) => Codec>>; instanceof: any>(c: Constructor) => Codec, InstanceType, unknown>>; exactStrict: >(wrappedInterfaceType: IT) => ObjectCodec; array: (item: C_3, name?: string | undefined) => Codec>; union: (codecs: CS, name?: string | undefined) => Codec>; record: (domain: D, codomain: C_4, name?: string | undefined) => Codec>; partial: (props: P_2, name?: string | undefined) => Codec>; literal: (value: V, name?: string | undefined) => Codec>; exact: (codec: C_5, name?: string | undefined) => Codec>; string: Codec; number: Codec; boolean: Codec; null: Codec; undefined: Codec; any: Codec; unknown: Codec; }; export { t }; export { isLeft, isRight } from 'fp-ts/lib/Either';