fix: require serializers for non-JSON cached values#50
Merged
Conversation
lan17
force-pushed
the
agent/honest-json-default-contract
branch
from
July 17, 2026 07:25
5d702eb to
585e185
Compare
lan17
marked this pull request as ready for review
July 17, 2026 19:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reframe issue #16 as a compile-time guardrail around the existing JSON default.
Cached functions whose resolved return types are statically JSON-compatible continue to omit
serializer. Known incompatible or unprovable return types now require a typed per-function serializer. Native JSON remains the default, and this adds no runtime validation pass.Architecture and design
JSON.stringify/JSON.parse, the top-levelundefinedsentinel, Redis framing, adapters, and fail-open behavior.Serializer<T>as a trusted boundary. DialCache does not perform a semantic round-trip check.Public API impact
CachedOptions<Fn>changes from an interface with an always-optional serializer to a conditional type:serializer?: Serializer<T> | null.serializer: Serializer<T>.This is a source-level tightening: code that cached non-JSON values without a per-function serializer will stop compiling until it makes the codec choice explicit. It also changes
CachedOptionsfrom an interface to a type alias, so declaration merging is no longer supported.The previous draft's public API change is reverted:
JsonSerializer<T>remains generic, and explicitly usingnew JsonSerializer<T>()remains a trusted caller assertion.Guard coverage and limits
The package declaration matrix accepts primitives, arrays, nested interface shapes, optional fields, empty objects, and top-level
undefined/void. It rejectsDate,Map,Set,bigint, functions, symbols, Buffers, typed arrays, method-bearing classes, required nestedundefined,unknown, andanyunless a matching serializer is present.The guard is conservative, not a proof. TypeScript cannot identify non-finite numbers, runtime cycles/shared references, runtime getter or
toJSONbehavior, or data-only class instances that look structural. Opaque, generic, or deeply recursive types may need an explicit serializer.V8 serialization is intentionally not added here; it remains a possible separate opt-in codec rather than a default change.
Validation
corepack pnpm checkon Node 22.22.0git diff --checkTracking
Closes #16