-
Notifications
You must be signed in to change notification settings - Fork 21
Description
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-wrapperalready handlesbigintserialization at runtime (via a customJSON.stringifyreplacer)- The
Jsonconstraint on the decoded type is overly restrictive for codecs likeBigIntFromStringthat encode to valid JSON