diff --git a/index.d.ts b/index.d.ts index d87a09e..519e395 100644 --- a/index.d.ts +++ b/index.d.ts @@ -44,21 +44,30 @@ export declare interface App { [namespace: string]: Package; } -export declare type Middleware = ( - req: Request, - res: Response, +export declare type Middleware< + TRequest extends Request = Request, + TResponse extends Response = Response +> = ( + req: TRequest, + res: TResponse, next: NextFunction ) => void; -export declare type ErrorHandlingMiddleware = ( +export declare type ErrorHandlingMiddleware< + TRequest extends Request = Request, + TResponse extends Response = Response +> = ( error: Error, - req: Request, - res: Response, + req: TRequest, + res: TResponse, next: NextFunction ) => void; export declare type ErrorCallback = (error?: Error) => void; -export declare type HandlerFunction = ( - req: Request, - res: Response, +export declare type HandlerFunction< + TRequest extends Request = Request, + TResponse extends Response = Response +> = ( + req: TRequest, + res: TResponse, next?: NextFunction ) => void | any | Promise; @@ -196,7 +205,7 @@ export declare class Request { [key: string]: any; } -export declare class Response { +export declare class Response { status(code: number): this; sendStatus(code: number): void; @@ -219,11 +228,11 @@ export declare class Response { callback?: ErrorCallback ): Promise; - send(body: any): void; + send(body: TBody): void; - json(body: any): void; + json(body: TBody): void; - jsonp(body: any): void; + jsonp(body: TBody): void; html(body: any): void; @@ -269,62 +278,157 @@ export declare class API { app(namespace: string, package: Package): App; app(packages: App): App; - get( + get( path: string, - ...middlewaresAndHandler: (Middleware | HandlerFunction)[] + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] + ): void; + get( + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] ): void; - get(...middlewaresAndHandler: (Middleware | HandlerFunction)[]): void; - post( + post< + TRequest extends Request = Request, + TResponse extends Response = Response + >( path: string, - ...middlewaresAndHandler: (Middleware | HandlerFunction)[] + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] + ): void; + post< + TRequest extends Request = Request, + TResponse extends Response = Response + >( + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] ): void; - post(...middlewaresAndHandler: (Middleware | HandlerFunction)[]): void; - put( + put( path: string, - ...middlewaresAndHandler: (Middleware | HandlerFunction)[] + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] + ): void; + put( + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] ): void; - put(...middlewaresAndHandler: (Middleware | HandlerFunction)[]): void; - patch( + patch< + TRequest extends Request = Request, + TResponse extends Response = Response + >( path: string, - ...middlewaresAndHandler: (Middleware | HandlerFunction)[] + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] + ): void; + patch< + TRequest extends Request = Request, + TResponse extends Response = Response + >( + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] ): void; - patch(...middlewaresAndHandler: (Middleware | HandlerFunction)[]): void; - delete( + delete< + TRequest extends Request = Request, + TResponse extends Response = Response + >( path: string, - ...middlewaresAndHandler: (Middleware | HandlerFunction)[] + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] ): void; - delete(...middlewaresAndHandler: HandlerFunction[]): void; - - options( + delete< + TRequest extends Request = Request, + TResponse extends Response = Response + >(...middlewaresAndHandler: HandlerFunction[]): void; + + options< + TRequest extends Request = Request, + TResponse extends Response = Response + >( path: string, - ...middlewaresAndHandler: (Middleware | HandlerFunction)[] + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] + ): void; + options< + TRequest extends Request = Request, + TResponse extends Response = Response + >( + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] ): void; - options(...middlewaresAndHandler: (Middleware | HandlerFunction)[]): void; - head( + head( path: string, - ...middlewaresAndHandler: (Middleware | HandlerFunction)[] + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] + ): void; + head( + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] ): void; - head(...middlewaresAndHandler: (Middleware | HandlerFunction)[]): void; - any( + any( path: string, - ...middlewaresAndHandler: (Middleware | HandlerFunction)[] + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] + ): void; + any( + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] ): void; - any(...middlewaresAndHandler: (Middleware | HandlerFunction)[]): void; - METHOD( + METHOD< + TRequest extends Request = Request, + TResponse extends Response = Response + >( method: METHODS | METHODS[], path: string, - ...middlewaresAndHandler: (Middleware | HandlerFunction)[] + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] ): void; - METHOD( + METHOD< + TRequest extends Request = Request, + TResponse extends Response = Response + >( method: METHODS | METHODS[], - ...middlewaresAndHandler: (Middleware | HandlerFunction)[] + ...middlewaresAndHandler: ( + | Middleware + | HandlerFunction + )[] ): void; register( @@ -336,9 +440,20 @@ export declare class API { routes(format: false): string[][]; routes(): string[][]; - use(path: string, ...middleware: Middleware[]): void; - use(paths: string[], ...middleware: Middleware[]): void; - use(...middleware: (Middleware | ErrorHandlingMiddleware)[]): void; + use( + path: string, + ...middleware: Middleware[] + ): void; + use( + paths: string[], + ...middleware: Middleware[] + ): void; + use( + ...middleware: ( + | Middleware + | ErrorHandlingMiddleware + )[] + ): void; finally(callback: FinallyFunction): void; diff --git a/index.test-d.ts b/index.test-d.ts index e4b68bd..cd30bf6 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -26,6 +26,23 @@ import { ALBEvent, } from 'aws-lambda'; +type MetricsLogger = { + setProperty(name: string, value: boolean): void; +}; + +interface TypedRequest extends Request { + params: { + thingId: string; + anotherThingId: string; + }; + context: Context & { metrics: MetricsLogger }; +} + +interface TypedResponseBody { + hello: string; + foo: string; +} + const options: Options = { base: '/api', version: 'v1', @@ -174,6 +191,10 @@ expectType( expectType(res.redirect('/new-path')); +const typedRes = {} as Response; +expectType(typedRes.json({ hello: 'thing', foo: 'another-thing' })); +expectError(typedRes.json({ hello: 'thing' })); + const middleware: Middleware = (req, res, next) => { next(); }; @@ -189,6 +210,37 @@ const handler: HandlerFunction = (req, res) => { }; expectType(handler); +const typedHandler: HandlerFunction> = ( + req, + res +) => { + const { metrics } = req.context; + metrics.setProperty('test', true); + res.json({ + hello: req.params.thingId, + foo: req.params.anotherThingId, + }); +}; +expectType>>( + typedHandler +); + +api.get>('/typed', typedHandler); +const invalidTypedHandler: HandlerFunction< + TypedRequest, + Response +> = (req, res) => { + expectError( + res.json({ + hello: req.params.thingId, + }) + ); +}; +api.get>( + '/typed-invalid', + invalidTypedHandler +); + const cookieOptions: CookieOptions = { domain: 'example.com', httpOnly: true,