express:扩展Express.Request的项目本地中间件

时间:2016-01-03 14:46:37

标签: express typescript typescript1.7

我正在研究基于express的节点服务器,并使用TypeScript 1.7编写。我正在使用一些特定于项目的中间件,这些中间件扩展了现有的快速请求或响应接口,但是我无法完全使用它(没有tsc抱怨在reqres中找不到X. )。我找到了关于这个问题的其他questions,但它们要么已经过时(我猜),要么解决方案不是直截了当。

我看了existing middleware的定义,但是如果没有手动编写单独的d.ts文件并在typings / tsd.d.ts中引用它们,我就无法使用它。这是我的设置:

// middleware/foobar.ts
declare module Express {
  export interface Request {
    foobar?: string;
  }
}

/* my project-related middleware extends the request by `foobar` */
export = function(req: Express.Request, res, next) {
  req.foobar = 'FooBar';
  next();
};

// main.ts
import express = require('express');

var app = express();

app.use(require('./middleware/foobar'));

app.get('/foobar', (req, res) => {
  /* tsc: Property 'foobar' does not exist on type 'Request' */
  res.send(req.foobar);
});

扩展表达式请求和响应接口的最佳做法是什么?如果可能的话,无需编写单独的d.ts,操纵typings目录中的任何内容或使用/// <reference path="..." />注释。

1 个答案:

答案 0 :(得分:1)

我自己找到了一个解决方案,使用this example作为参考。我的中间件需要包装在一个声明的模块中,所以中间件/ foobar.ts看起来像这样:

declare module Express {
  export interface Request {
    foobar?: string;
  }
}

declare module 'foobar' {
  function foobar(req: Express.Request, res, next) {
    req.foobar = 'FooBar';
    next();
  }

  export = foobar;
}
如果你在中间件中使用类或其他导入的东西,那就更麻烦了。在我的例子中,我的中间件使用我自己的&#34; EntityManager&#34; class,它是数据库连接的抽象(对我来说是mysql)。我的中间件(对我来说是middleware/database.ts)现在看起来像这样:

declare module Express {
  import { Manager as EntityManager } from 'entity-manager';

  export interface Request {
    entityManager?: EntityManager;
  }
}

declare module 'database' {
  import * as mysql from 'mysql';
  import { Manager as EntityManager } from 'entity-manager';

  /* some middleware-related code */
  var pool = mysql.createPool(...);
  var entityManager = new EntityManager(pool);
  /* *** */


  /* the actual exported function */
  function database(req: Express.Request, res, next) {
    req.entityManager = entityManager;
    next();
  };

  export = database;
}

请注意,我的EntityManager类被导入两次,每个模块声明一次。只是在两个模块上方导入它似乎没有用。

<强>更新

将实际代码放在声明的模块中(在我的情况下为'database')在JS文件中没有输出。

在常规模块中包含该代码需要名称不在撇号中(例如,不允许使用连字符)并且也不会生成单函数导出代码。

将实际代码完全放在模块之外(因此只有声明的Express模块​​带有扩展请求)会产生正确的JS,但我的文本编辑器不能再找到entityManager

似乎我需要将打字(例如我自己的Express.Request扩展名)放入专用的d.ts文件中,其中不存在实际代码。