Skip to content

fix(types): make request Refs covariant#4585

Draft
damusix wants to merge 1 commit into
hapijs:masterfrom
damusix:fix/reqref-variance
Draft

fix(types): make request Refs covariant#4585
damusix wants to merge 1 commit into
hapijs:masterfrom
damusix:fix/reqref-variance

Conversation

@damusix

@damusix damusix commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Typed routes, lifecycle methods, pres, failActions, and extensions currently error whenever their Refs are not 100% identical — the limitation documented in test/types/index.ts ("Request not assignable to Request"). Three compounding causes:

  1. Request embeds Lifecycle.Method<Refs> through route.settings, whose contravariant request parameter makes Refs effectively invariant — even plain widening (Request<{Payload: X}>Request) fails.
  2. Two contravariant keyof positions (paramsArray, pre assign) additionally block covariance. paramsArray was also mistyped: it holds the param values in path order, so it is string[].
  3. TypeScript relates Request<A> to Request<B> by comparing the type arguments directly, and a partial Refs object can never satisfy the full ReqRefDefaults interface. The type parameter therefore now defaults to {} — reads are unchanged, since MergeRefs<{}> resolves to the same defaults.

The fix: Lifecycle.Method is declared through a method signature so comparisons are bivariant (the same technique React's typings use for event handlers), Request/ResponseToolkit are annotated out with the {} default, and the two keyof positions are made covariant-safe (assign keeps declared-key autocomplete via Extract<keyof ...> | (string & {})).

Net effect: a method typed with narrower refs attaches to any surface typed with the defaults (server.ext(), route ext, failAction, pre on untyped routes), and a route typed with a superset of refs accepts methods typed with any subset — while contradictory refs and default-to-narrow flows still error. Types-only; no runtime change.

Typed lifecycle methods failed to attach to any surface whose Refs
were not identical. Method is now bivariant, Request/ResponseToolkit
covariant with an empty-bag default; paramsArray was mistyped as keys.
@damusix
damusix force-pushed the fix/reqref-variance branch from 0d734b2 to b558579 Compare July 21, 2026 18:37
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