Skip to content

feat(types)!: type deserialize's input as a JSON:API document - #221

Open
mamhoff wants to merge 1 commit into
mainfrom
feat/typed-deserialize-document
Open

mamhoff wants to merge 1 commit into
mainfrom
feat/typed-deserialize-document

Conversation

@mamhoff

@mamhoff mamhoff commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

deserialize<T = unknown>(document: unknown): T accepts anything, so a caller can annotate its API call with the deserialized type, pass it in, and nothing checks the boundary. Type the input as the JSON:API document it is instead, and export the v1.1 document types (JsonApiDocument, JsonApiResource, JsonApiRelationship, JsonApiResourceIdentifier, JsonApiLinks, ...) so callers can type the raw response.

T stays unconstrained, and no longer has a default: what comes out depends on the endpoint, so the caller names the type it expects (an unnamed T infers unknown). The implementation returns any internally rather than describing a structure that would be cast to T.

The deprecated deserializePage/deserializePages aliases get the same input type.

Type-level specs live in deserialize.types.spec.ts, and pnpm typecheck now also compiles the specs (they were excluded before).

BREAKING CHANGE: TypeScript callers must pass a value typed as JsonApiDocument (or structurally compatible with it). Values typed unknown and documents with numeric ids no longer compile. Runtime behaviour is unchanged.

`deserialize<T = unknown>(document: unknown): T` accepts anything, so a
caller can annotate its API call with the *deserialized* type, pass it
in, and nothing checks the boundary. Type the input as the JSON:API
document it is instead, and export the v1.1 document types
(`JsonApiDocument`, `JsonApiResource`, `JsonApiRelationship`,
`JsonApiResourceIdentifier`, `JsonApiLinks`, ...) so callers can type
the raw response.

`T` stays unconstrained, and no longer has a default: what comes out
depends on the endpoint, so the caller names the type it expects (an
unnamed `T` infers `unknown`). The implementation returns `any`
internally rather than describing a structure that would be cast to `T`.

The deprecated `deserializePage`/`deserializePages` aliases get the same
input type.

Type-level specs live in `deserialize.types.spec.ts`, and `pnpm
typecheck` now also compiles the specs (they were excluded before).

BREAKING CHANGE: TypeScript callers must pass a value typed as
`JsonApiDocument` (or structurally compatible with it). Values typed
`unknown` and documents with numeric ids no longer compile. Runtime
behaviour is unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant