chore(express): remove redundant option-object casts - #114
Merged
Conversation
Strip the as any and as SomeOptions casts on the option literals passed to the core handlers. These casts disabled excess-property checking, which is what let a mistyped option be silently dropped in the getSeamlessUser regression. Removing them lets the compiler check each literal against its handler interface. Delete the dead forwardedClientIp: undefined property on the ensureCookies middleware options (the value is computed per request), and replace the blanket req.query cast in the metrics handlers with a small normalizer that reduces Express's ParsedQs to the scalar query record the core handler declares. No public API change.
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
Removes all 41
as any/ option-object casts from the Express adapter so the compiler checks each option literal against its handler interface. These casts are the exact construct that let thegetSeamlessUserserviceAuthorizationoption be silently dropped (#99): the cast disables excess-property checking, so a mistyped or renamed option compiles clean and vanishes at runtime.Closes #106.
What was hidden
Exactly as the #106 audit predicted, only one cast was hiding anything real: a dead
forwardedClientIp: undefinedproperty on thecreateEnsureCookiesMiddlewareoptions literal, which is not inEnsureCookiesMiddlewareOptions(the real value is computed per request inside the middleware). Removing the cast surfaced it as a compile error; it is now deleted. Every other literal type-checks cleanly against its interface, confirming none currently drops a live option.The metrics query cast
internalMetrics.tsusedquery: req.query as any. Express typesreq.queryasParsedQs, which genuinely is not the scalarRecord<string, string | number | boolean | undefined>the core handler declares, so this cast was doing real (if unsound) work. Replaced with atoQueryRecordnormalizer rather than another cast.One visible edge case worth calling out: previously an array-valued query param (
?type=a&type=b) reached the upstream comma-joined viaString(['a','b']). The scalar handler contract never supported arrays, and the normalizer now takes the first value. Metrics filters are scalar by design (date ranges, group-by keys), so this only affects an input the contract never modeled.Not a cast
clientErrorStatus'serr as { status?: unknown }narrowing and theresult: anyhandler params are legitimate and untouched. Scope was strictly the option-literal casts.Checks
Identical test counts to before, confirming no behavior change. No em dashes. Changeset included (patch, express).