chrisber
chrisber

Reputation: 770

Express.js routes with Typescript

I want to use Express.js with Typescript to specify the code more modular/OO.

I want to implement a Route/Controller by implementing the IRoute interface and then adding the new Route to app.use().

The problem I'm facing is that each operation (get,post,put,delete) itself returns the IRoute interface and I'm not sure what to return to. To return return <IRoute> this; in an operation is not working.

The typescript compiler response with the following error message:

Class MessurmentsController incorrectly implements interface IRoute. Types of property all are incomatible. Type (req: Request, res: Response, next: Function) => void is not assignable to type (...handler: RequestHandler[]): IRoute. Types of parameters req and handler are incomatible. Type Request is not assignable to type RequestHandler.

/// <reference path="../../../typings/tsd.d.ts" />

import {IRoute, Request,Response}  from 'express';


export class MeasurementsController implements IRoute {
	path: string;
	stack: any;
	
	constructor(){
		this.path = "/api/measurements"
	}
	
	
	all(req: Request, res: Response, next: Function){
		res.send('');
        //return <IRoute> this;
	}
	
	get(req: Request, res: Response, next: Function){
		res.send('');
	}
	
	post(req: Request, res: Response, next: Function){
		res.send('');
	}
	
	put(req: Request, res: Response, next: Function){
		res.send('');
	}
	
	delete(req: Request, res: Response, next: Function){
		res.send('');
	}
	patch(req: Request, res: Response, next: Function){
		res.send('');
	}
	options(req: Request, res: Response, next: Function){
		res.send('');
	}
	head(req: Request, res: Response, next: Function){
		res.send('');
	}
}

The Route in d.ts is defined as

    module e {
        interface IRoute {
            path: string;
            stack: any;
            all(...handler: RequestHandler[]): IRoute;
            get(...handler: RequestHandler[]): IRoute;
            post(...handler: RequestHandler[]): IRoute;
            put(...handler: RequestHandler[]): IRoute;
            delete(...handler: RequestHandler[]): IRoute;
            patch(...handler: RequestHandler[]): IRoute;
            options(...handler: RequestHandler[]): IRoute;
            head(...handler: RequestHandler[]): IRoute;
        }

Any Idea of what I need to return in an operation to get this working?

Upvotes: 5

Views: 8316

Answers (3)

Eliav Louski
Eliav Louski

Reputation: 5214

this issue had annoyed me enough so in my last project i ended up writing my own typescript wrapper which i later extracted into standalone library.

You can checkout my type-safe typescript router wrapper: express-typed.

express-typed implement exactly what this question asks: a type-safe express router.

implementing the demo provided in the question would be simple as

import { TypedRequest, TypedResponse, TypedRouter, ParseRoutes, GetRouteResponseInfo } from "express-typed";

const typedRouter = new TypedRouter({
  // returned type is inferred
  "/api/Admin": {
    get: (req, res) => {
      return res.send("get: /api/Admin").status(200);
    },
  }
});

export default typedRouter;

export type AppRoutes = ParseRoutes<typeof typedRouter>;

// getting the type is simple as:
type ApiAdminResponse = GetRouteResponseInfo<AppRoutes, "/api/Admin", "get">;
//   ^? type ApiAdminResponse = "get: /api/Admin"

read more at the repo.

Upvotes: 0

Natarajan Ganapathi
Natarajan Ganapathi

Reputation: 575

I hope this will help you.

export class Admin implements IRoute {
    path: string;
    stack: any;
    constructor() {
        this.path = '/api/Admin';
    }

    all(handerl: RequestHandler): any {
        return <IRoute>this;
    }
    get(handerl: RequestHandler): any {
        return <IRoute>this;
    }
    post(handerl: RequestHandler): any {
        return <IRoute>this;
    }
    put(handerl: RequestHandler): any {
        return <IRoute>this;
    }
    delete(handerl: RequestHandler): any {
        return <IRoute>this;
    }
    patch(handerl: RequestHandler): any {
        return <IRoute>this;
    }
    options(handerl: RequestHandler): any {
        return <IRoute>this;
    }
    head(handerl: RequestHandler): any {
        return <IRoute>this;
    }
}

Upvotes: 2

chrisber
chrisber

Reputation: 770

Finally a solution emerged:

routing-controllers Allows to create controller classes with methods as actions that handle requests. You can use routing-controllers with express.js or koa.js. https://github.com/pleerock/routing-controllers

Upvotes: 5

Related Questions