TypedRequestHandler
Type
A TypeScript helper type provided by @api-ts/typed-express-router
to help you define
Express route handlers with correctly inferred types for the augmented request
and
response
objects.
Purpose:
When defining handlers for "checked" routes (such as using typedRouter.get(...)
), this
type automatically infers:
- The type of
req.decoded
based on therequest
codec of the specifichttpRoute
linked via theoperationName
. - The type signature of
res.sendEncoded
, ensuring thepayload
type is checked against the appropriateresponse
codec for the givenstatus
code from thehttpRoute
.
Definition (Conceptual):
import express from 'express';
import { HttpRoute } from '@api-ts/io-ts-http'; // Conceptual import
import * as t from 'io-ts'; // For TypeOf and OutputOf
// RouteDefinition represents the specific httpRoute object from the ApiSpec
// e.g., MyApi['my.operation']['get']
type RouteDefinition = HttpRoute<any, any>;
// Extracts the decoded request type from the route's request codec
type DecodedRequest<R extends RouteDefinition> = t.TypeOf<R['request']>;
// Represents the augmented response object
type TypedResponse<R extends RouteDefinition> = express.Response & {
sendEncoded<Status extends keyof R['response'] & number>( // Status must be a key in response obj
status: Status,
// Payload type must match the codec for the given status
payload: t.TypeOf<R['response'][Status]>,
): TypedResponse<R>; // Allows chaining like standard Express res
};
export type TypedRequestHandler<RouteDef extends RouteDefinition = any> = (
req: express.Request & { decoded: DecodedRequest<RouteDef> },
res: TypedResponse<RouteDef>,
next: express.NextFunction,
) => void | Promise<void>; // Allow async handlers
(Note: The actual implementation may involve more complex generic constraints)
Usage: Import the type and use it when defining your handler functions. Provide the
specific httpRoute
definition type from your imported ApiSpec
as the generic
argument.
import express from 'express';
import { TypedRequestHandler } from '@api-ts/typed-express-router';
import { MyApi } from 'my-api-package'; // Your generated ApiSpec object
// Define the type for the specific route handler
type HelloWorldRouteHandler = TypedRequestHandler<MyApi['hello.world']['get']>;
// ^------------------------------^
// Generic argument points to the specific httpRoute definition in the spec
const handler: HelloWorldRouteHandler = (req, res, next) => {
// req.decoded is strongly typed based on MyApi['hello.world']['get'].request
const name = req.decoded.name || 'World';
// Payload for status 200 is type-checked against MyApi['hello.world']['get'].response[200]
res.sendEncoded(200, { message: `Hello, ${name}!` });
// If status 400 was defined in the spec with a different payload type:
// const errorPayload = { error: 'Missing name' };
// res.sendEncoded(400, errorPayload); // This would also be type-checked
};
// Use the handler
// typedRouter.get('hello.world', [handler]);
Using TypedRequestHandler
significantly improves your developer experience by
providing type safety and autocompletion for the decoded request properties and the
sendEncoded
payload within route handlers.