diff --git a/packages/io-ts-http/src/httpRequest.ts b/packages/io-ts-http/src/httpRequest.ts index 35f5b257..fdb8b806 100644 --- a/packages/io-ts-http/src/httpRequest.ts +++ b/packages/io-ts-http/src/httpRequest.ts @@ -1,7 +1,6 @@ import * as t from 'io-ts'; import { Json } from 'io-ts-types'; import { flattened, optional, optionalized } from './combinators'; -import { OutputConstrainedProps } from './utils'; export const GenericHttpRequest = optionalized({ // DISCUSS: renaming this to something more specific, e.g. route, or path, or routeParams, or pathParams @@ -18,13 +17,46 @@ export type HttpRequestCodec = t.Type< >; export type HttpRequestCombinatorProps = { - params?: NonNullable>; - query?: NonNullable>; - headers?: NonNullable>; + params?: NonNullable; + query?: NonNullable; + headers?: NonNullable; body?: NonNullable; }; -export function httpRequest(props: Props) { +/** + * Attempts to produce a helpful error message when invalid codecs are passed to `httpRequest` + * It is a workaround until something like https://github.com/microsoft/TypeScript/pull/40468 + * is merged. + */ +type EmitOutputTypeErrors< + P extends t.Props | undefined, + O, + OName extends string, +> = P extends undefined + ? P + : { + [K in keyof P & string]: P[K] extends t.Type + ? P[K] + : `Codec's output type is not assignable to ${OName}. Try using one like \`NumberFromString\``; + }; + +type EmitPropsErrors

= { + params?: EmitOutputTypeErrors; + query?: EmitOutputTypeErrors< + P['query'], + string | string[] | undefined, + 'string | string[] | undefined' + >; + headers?: EmitOutputTypeErrors< + P['headers'], + string | undefined, + 'string | undefined' + >; +}; + +export function httpRequest< + Props extends HttpRequestCombinatorProps & EmitPropsErrors, +>(props: Props) { return flattened('httpRequest', { query: {}, params: {}, diff --git a/packages/io-ts-http/src/utils.ts b/packages/io-ts-http/src/utils.ts index a071ee57..a7504dde 100644 --- a/packages/io-ts-http/src/utils.ts +++ b/packages/io-ts-http/src/utils.ts @@ -26,10 +26,6 @@ export type OptionalizedC = t.IntersectionC< [t.TypeC>, t.PartialC>] >; -export type OutputConstrainedProps = { - [K: string]: t.Type; -}; - export type NestedProps = { [K: string]: t.Props; };