typeorm / typescript-express-example

Example how to use Express and TypeORM with TypeScript
359 stars 100 forks source link

TypeScript compilerOptions -> "strict" : true #8

Open cgers opened 5 years ago

cgers commented 5 years ago

Hi There

In typescript-express-example/src/index.ts you have some beautifully elegant code:

` // register all application routes

AppRoutes.forEach(route => {

    app[route.method](route.path, (request: Request, response: Response, next: Function) => {

        route.action(request, response)

            .then(() => next)

            .catch(err => next(err));

    });

});

`

That registers all applications routes.

If you enable

"strict": true

in the tsconfig.json I get the error:

`src/index.ts:19:4 - error TS7017: Element implicitly has an 'any' type because type 'Express' has no index signature. 19 app[route.method](route.path, (request: Request, response: Response, next: Function) => {


`

Is there a way to combine modules in this elegant way and enable strict?

Kind regards
mrnkr commented 4 years ago

Well, this is awkward. Just started getting into typeorm today, really liking it, stumbled upon this question, tried the first solution that came to my mind and it worked! In case anyone will still find it useful I'll leave it here 🤓

The solution is to type AppRoutes as an array of Route. That Route interface has to look like this:

export interface Route {
  path: string;
  method: 'get' | 'post' | 'put' | 'delete';
  action:  (req: Request, res: Response) => Promise<void>;
}

This way you tell typescript exactly what strings to expect in that method key, hence it does not think it is viable for an invalid key to pop up there. I omitted the last argument for the action (next) on purpose, but do add it if you want it there!

Again, hope this helps someone! Happy coding!

ScottWallace commented 3 years ago

That is a wonderfully elegant piece of code, but it needs middleware, especially authentication middleware. Here's how to do it:

Add an element to the path objects that need authentication in the routes.ts file, called "secure". Not every element needs it.

  {
    path: '/users/user/prayers',
    method: 'post',
    action: GetUserPrayersAction
  },
  {
    path: '/users/user/settings/profileurl',
    method: 'post',
    action: SetUserProfilePictureAction,
    secure: true
  },

Now use this code in place of your standard AppRoutes.forEach:

  // register all application routes
  AppRoutes.forEach(route => {
    if (route.secure != true) {
      app[route.method](route.path, (request: Request, response: Response, next: Function) => {
        route.action(request, response)
          .then(() => next)
          .catch(err => next(err));
      });
    }
    else {
      app[route.method](route.path, firebaseService.authenticationMiddleware(), (request: Request, response: Response, next: Function) => {
        route.action(request, response)
          .then(() => next)
          .catch(err => next(err));
      });
    }
  });

You should replace firebaseService.authenticationMiddleware() with whatever middleware you want to provide.

Fun!