26

using Express in a Node project along with Typescript what would be the "best practices" for express.Router.

example directory structure

|directory_name
  ---server.js
  |--node_modules
  |--routes
     ---index.ts
     |--admin
        ---admin.ts
     |--products
        ---products.ts
     |--authentication
        ---authentication.ts

so inside index.ts it would encapsulate and manage all the sub-routers

    //admin.ts (nested inside of index.ts)
    import * as express from "express";

    export = (() => {
        
        let router = express.Router();
              
        router.get('/admin', (req, res) => {
            res.json({success: true});
        });
        
        return router;
    })();

    //index.ts (master file for express.Router)

    import * as express from "express";

    //import sub-routers
    import * as adminRouter from "./admin/admin";
    import * as productRouter from "./products/products";

    export = (() => {

      let router = express.Router();

      // mount express paths, any addition middleware can be added as well.
      // ex. router.use('/pathway', middleware_function, sub-router);

      router.use('/products', productRouter);
      router.use('/admin', adminRouter);

      //return for revealing module pattern
      return router;
    })(); //<--- this is where I don't understand something....

lastly we would set-up our server.js

    //the usual node setup
    //import * as *** http, body-parser, morgan, mongoose, express <-- psudocode

    import * as masterRouter from './routes/index'

    var app = express();
    //set-up all app.use()

    app.use('/api', masterRouter);

    http.createServer(app).listen(8080, () => {
          console.log('listening on port 8080')
        };

my main question really is, is index.ts (masterRouter file) and it's nested routes that are IIFe's

export = (function(){})();

should that be the correct/best way to write typescript modules for routers?

or would it be better to use another pattern, perhaps one the utilizes the pattern

export function fnName() {} -- export class cName {} -- export default.

the reason for the IIFe is that when i import them into another file i won't need to initialize the module and there will only ever be 1 instance of each type of router.

Andrei
  • 1,196
  • 1
  • 11
  • 25

1 Answers1

36

In NodeJS each file is a module. Declaring variables does not pollute the global namespace. So you don't need to use the good old IIFE trick to properly scope variables (and prevent global pollution / collision).

You would write:

  import * as express from "express";

  // import sub-routers
  import * as adminRouter from "./admin/admin";
  import * as productRouter from "./products/products";

  let router = express.Router();

  // mount express paths, any addition middleware can be added as well.
  // ex. router.use('/pathway', middleware_function, sub-router);

  router.use('/products', productRouter);
  router.use('/admin', adminRouter);

  // Export the router
  export = router;

More on modules: https://basarat.gitbooks.io/typescript/content/docs/project/modules.html

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
basarat
  • 261,912
  • 58
  • 460
  • 511
  • 1
    that meme is a killer, thank you very much for the link! – Andrei May 12 '16 at 00:54
  • 1
    Upgrading to TS2 using @types/express this throws a `error TS4023: Exported variable 'router' has or is using name 'Router' from external module "[...]/node_modules/@types/express-serve-static-core/index" but cannot be named.`. Any ideas how to fix that? – Aides Jan 24 '17 at 15:53
  • Apparently the solution is to explicitly annotate the router variable (see [http://stackoverflow.com/questions/41847314](http://stackoverflow.com/questions/41847314/exported-variable-router-has-or-is-using-name-router-from-external-module-bu)) – Aides Jan 25 '17 at 09:05
  • 1
    oh, the meme is gone... :( – dcsan Jul 01 '19 at 15:53
  • 1
    Have a problem on: `export = router;` "Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead." – Andres Gardiol Sep 11 '19 at 15:13
  • 1
    @AndresGardiol using ECMAScript modules aka es2015 modules, if I'm not mistaken it's simply `export router;`. When I originally posted this it was based on Node.js module system which had an object `export` that could be used. With the new module import/export system I believe it should work. – Andrei Nov 14 '19 at 15:51
  • 1
    Memes on StackOverflow... Rare thing to see xD – user0103 Oct 14 '20 at 13:44
  • it should be : export {router}; – Ali Jan 29 '22 at 09:16
  • your link `https://basarat.gitbooks.io/typescript/content/docs/project/modules.html` was moved and returns a 404 now, the page is now at https://basarat.gitbook.io/typescript/project/modules – robin Oct 17 '22 at 21:47