Skip to content

Commit 14343c6

Browse files
committed
feat: produce helpful error messages on httpRequest codec errors
Attempts to produce a helpful error message when invalid codecs are passed to `httpRequest`. It is a workaround until something like microsoft/TypeScript#40468 is merged.
1 parent 8195fa0 commit 14343c6

File tree

2 files changed

+37
-9
lines changed

2 files changed

+37
-9
lines changed

packages/io-ts-http/src/httpRequest.ts

+37-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as t from 'io-ts';
22
import { Json } from 'io-ts-types';
33
import { flattened, optional, optionalized } from './combinators';
4-
import { OutputConstrainedProps } from './utils';
54

65
export const GenericHttpRequest = optionalized({
76
// DISCUSS: renaming this to something more specific, e.g. route, or path, or routeParams, or pathParams
@@ -18,13 +17,46 @@ export type HttpRequestCodec<T> = t.Type<
1817
>;
1918

2019
export type HttpRequestCombinatorProps = {
21-
params?: NonNullable<OutputConstrainedProps<string | undefined>>;
22-
query?: NonNullable<OutputConstrainedProps<string | string[] | undefined>>;
23-
headers?: NonNullable<OutputConstrainedProps<string | undefined>>;
20+
params?: NonNullable<t.Props>;
21+
query?: NonNullable<t.Props>;
22+
headers?: NonNullable<t.Props>;
2423
body?: NonNullable<t.Props>;
2524
};
2625

27-
export function httpRequest<Props extends HttpRequestCombinatorProps>(props: Props) {
26+
/**
27+
* Attempts to produce a helpful error message when invalid codecs are passed to `httpRequest`
28+
* It is a workaround until something like https://github.com/microsoft/TypeScript/pull/40468
29+
* is merged.
30+
*/
31+
type EmitOutputTypeErrors<
32+
P extends t.Props | undefined,
33+
O,
34+
OName extends string,
35+
> = P extends undefined
36+
? P
37+
: {
38+
[K in keyof P & string]: P[K] extends t.Type<any, O, any>
39+
? P[K]
40+
: `Codec's output type is not assignable to ${OName}. Try using one like \`NumberFromString\``;
41+
};
42+
43+
type EmitPropsErrors<P extends HttpRequestCombinatorProps> = {
44+
params?: EmitOutputTypeErrors<P['params'], string | undefined, 'string | undefined'>;
45+
query?: EmitOutputTypeErrors<
46+
P['query'],
47+
string | string[] | undefined,
48+
'string | string[] | undefined'
49+
>;
50+
headers?: EmitOutputTypeErrors<
51+
P['headers'],
52+
string | undefined,
53+
'string | undefined'
54+
>;
55+
};
56+
57+
export function httpRequest<
58+
Props extends HttpRequestCombinatorProps & EmitPropsErrors<Props>,
59+
>(props: Props) {
2860
return flattened('httpRequest', {
2961
query: {},
3062
params: {},

packages/io-ts-http/src/utils.ts

-4
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ export type OptionalizedC<Props extends t.Props> = t.IntersectionC<
2626
[t.TypeC<RequiredProps<Props>>, t.PartialC<OptionalProps<Props>>]
2727
>;
2828

29-
export type OutputConstrainedProps<O> = {
30-
[K: string]: t.Type<any, O, unknown>;
31-
};
32-
3329
export type NestedProps = {
3430
[K: string]: t.Props;
3531
};

0 commit comments

Comments
 (0)