Augmented Request & Response
When you use route handlers registered via a TypedRouter
object
(using methods like .get
, .post
, .getUnchecked
, etc.), the standard Express
request
and response
objects are augmented with additional properties and methods
related to the API specification.
Augmented Request (req
)
The Express request
object (req
) passed to typed route handlers includes an
additional property:
req.decoded
- Type (Checked Routes):
DecodedRequest
- In handlers attached using the "checked" methods (such as
typedRouter.get(...)
),req.decoded
holds the successfully decoded and validated request data. Its TypeScript type is inferred directly from therequest
codec defined in the correspondinghttpRoute
of theApiSpec
. This object contains the flattened combination of path parameters, query parameters, headers, and body properties as defined by thehttpRequest
codec used in the spec.
- In handlers attached using the "checked" methods (such as
- Type (Unchecked Routes & Middleware):
Either<t.Errors, DecodedRequest>
- In handlers attached using the "unchecked" methods (such as
typedRouter.getUnchecked(...)
) or in middleware added viatypedRouter.use(...)
,req.decoded
holds the raw result of the decoding attempt fromio-ts
. This is anEither
type from thefp-ts
library. - Use
E.isRight(req.decoded)
to check if decoding was successful. If true,req.decoded.right
contains theDecodedRequest
. - Use
E.isLeft(req.decoded)
to check if decoding failed. If true,req.decoded.left
contains thet.Errors
object detailing the validation failures.
- In handlers attached using the "unchecked" methods (such as
Augmented Response (res
)
The Express response
object (res
) passed to typed route handlers includes an
additional method:
res.sendEncoded(status, payload)
Use this method instead of res.json()
or res.send()
when sending responses that
should conform to the API specification.
Parameters:
status
(number
): The HTTP status code for the response. This status code must be a key defined in theresponse
object of thehttpRoute
associated with the current route in theApiSpec
.payload
(any
): The data to be sent as the response body.
Behavior:
- Type Checking: Validates that the provided
payload
conforms to theio-ts
codec associated with the givenstatus
in thehttpRoute
'sresponse
definition. - Encoding: Encodes the
payload
using the sameio-ts
codec. This handles necessary transformations (such as converting aDate
object to an ISO string if usingDateFromISOString
, or abigint
to a string if usingBigIntFromString
). - Sending Response: Sets the response status code to
status
, sets theContent-Type
header toapplication/json
, and sends the JSON-stringified encoded payload as the response body. - Error Handling: If the
payload
fails validation against the codec for the specifiedstatus
, calls theonEncodeError
hook (route-specific or global). - Post-Response Hook: After the response has been successfully sent, calls the
afterEncodedResponseSent
hook (route-specific or global).
Example:
import { TypedRequestHandler } from '@api-ts/typed-express-router';
import { MyApi } from 'my-api-package';
// Assuming 'api.v1.getUser' route expects a { user: UserType } payload for status 200
const getUserHandler: TypedRequestHandler<MyApi['api.v1.getUser']['get']> = (
req,
res,
) => {
const userId = req.decoded.userId; // Access decoded request data
const user = findUserById(userId);
if (!user) {
// Assuming 404 is defined in the spec with an error object payload
res.sendEncoded(404, { error: 'User not found' });
return;
}
// Send status 200 with the UserType payload
// 'sendEncoded' ensures 'user' matches the spec for status 200
res.sendEncoded(200, { user: user });
};