v10.0.5
Fix: optional handling now matches direction of data flow
The previous exact / coerced split conflated two orthogonal concerns — whether to coerce wire strings and whether to tolerate undefined. The result: server-side hono middleware and client-side response parsing were both wrapping optional fields in v.optional(...), which permits undefined even though JSON-parsed wire data can never carry one. Handlers had to defensively guard against { field: undefined } cases that were structurally impossible.
Realigned the schemas along direction of data flow:
-
inputXxxSchema— for outgoing TS-side values (request bodies beforeJSON.stringify, pre-flight validation). Usesv.optional(...). No wire coercion (types are already TS-native). Tolerates the destructure-with-default{ foo: undefined }pattern. -
xxxSchema(wire) — for incoming JSON-parsed values (hono middleware, rest-client response parsing). Usesv.exactOptional(...)— field is present-with-value or absent, never undefined. Includes bigint / number coercion for HTTP wire formats.
For server handlers, the win is concrete: c.req.valid(\"json\") now returns { name: string, nickname?: string } rather than { name: string, nickname: string | undefined }. No phantom-undefined to guard against.
Renames
| Before | After |
|---|---|
exactPetSchema |
inputPetSchema |
petSchema (with v.optional + coercion) |
petSchema (with v.exactOptional + coercion) |
--exact-only |
--input-only |
CodegenOptions.exactOnly |
CodegenOptions.inputOnly |
SchemaMode "exact" / "coerced" |
"input" / "wire" |
Behavioral changes
petSchema(wire variant, same name as before): optional fields now usev.exactOptionalinstead ofv.optional. Strictly correct for JSON-parsed data; would reject{ field: undefined }if it ever appeared (it can't, afterJSON.parse).exactPetSchema→inputPetSchema: optional handling flipped fromv.exactOptionaltov.optional. Use this for client-side pre-flight validation where TS callers may pass undefineds.
Versioning note
Strictly a major bump (renames + flipped semantics). Released as patch given a single pre-launch consumer.