Problem
GenericHttpRequest defines its body as optional(Json):
// packages/io-ts-http/src/httpRequest.ts
export const GenericHttpRequest = optionalized({
// ...
body: optional(Json),
});
This produces body: t.UnionC<[t.Type<Json, Json, unknown>, t.UndefinedC]>, constraining both the decoded type (A) and encoded type (O) to Json.
Json is boolean | number | string | null | JsonArray | JsonRecord — it does not include bigint.
When a route intersects GenericHttpRequest with a body codec that uses BigIntFromString (from io-ts-types), the decoded type contains bigint, which is not assignable to Json. This causes a type error on the superagent-wrapper client side when calling .post(), because the parameter type is RequestType<Route> (i.e., t.TypeOf<request> — the decoded type).
BigIntFromString is t.Type<bigint, string, unknown> — it encodes bigint → string, which is valid Json. So the wire format is fine; only the decoded (in-memory) type violates the constraint.
Example
import { GenericHttpRequest, httpRoute } from '@api-ts/io-ts-http';
import { BigIntFromString } from 'io-ts-types';
import * as t from 'io-ts';
const MyRequest = t.type({ amount: BigIntFromString });
const route = httpRoute({
path: '/transfer',
method: 'POST',
request: t.intersection([
GenericHttpRequest,
t.type({ body: MyRequest }),
]),
response: { 200: t.unknown },
});
// On the superagent-wrapper client:
// client['transfer'].post({ query: {}, body: { amount: 100n } })
// ^^^^
// TS2345: Type 'bigint' is not assignable to type 'Json'
Documentation discrepancy
The Docusaurus reference docs describe GenericHttpRequest as having body?: unknown, but the code constrains it to body?: Json.
Suggestion
Relax the body constraint to optional(t.unknown):
export const GenericHttpRequest = optionalized({
params: t.record(t.string, t.string),
query: t.record(t.string, t.union([t.string, t.array(t.string)])),
headers: optional(t.record(t.string, t.string)),
body: optional(t.unknown),
});
This matches the docs, and is safe because:
- Each route already specifies its own body codec with the actual constraint
superagent-wrapper already handles bigint serialization at runtime (via a custom JSON.stringify replacer)
- The
Json constraint on the decoded type is overly restrictive for codecs like BigIntFromString that encode to valid JSON
Problem
GenericHttpRequestdefines its body asoptional(Json):This produces
body: t.UnionC<[t.Type<Json, Json, unknown>, t.UndefinedC]>, constraining both the decoded type (A) and encoded type (O) toJson.Jsonisboolean | number | string | null | JsonArray | JsonRecord— it does not includebigint.When a route intersects
GenericHttpRequestwith a body codec that usesBigIntFromString(fromio-ts-types), the decoded type containsbigint, which is not assignable toJson. This causes a type error on thesuperagent-wrapperclient side when calling.post(), because the parameter type isRequestType<Route>(i.e.,t.TypeOf<request>— the decoded type).BigIntFromStringist.Type<bigint, string, unknown>— it encodesbigint → string, which is validJson. So the wire format is fine; only the decoded (in-memory) type violates the constraint.Example
Documentation discrepancy
The Docusaurus reference docs describe
GenericHttpRequestas havingbody?: unknown, but the code constrains it tobody?: Json.Suggestion
Relax the body constraint to
optional(t.unknown):This matches the docs, and is safe because:
superagent-wrapperalready handlesbigintserialization at runtime (via a customJSON.stringifyreplacer)Jsonconstraint on the decoded type is overly restrictive for codecs likeBigIntFromStringthat encode to valid JSON