扩展@types声明的现有属性

时间:2018-01-06 16:59:16

标签: typescript typescript-typings

我正在尝试扩展 express.Request 上提供的快递请求对象,以便它包含其中的一些其他数据会话。我尝试创建自己的打字文件( d.ts )并使用以下代码:

import * as express from 'express';

declare module 'express' {
    export interface Request {
        session: express.Request['session'] & {
            myOwnData: string;
        }
    }
}

我受到以下错误

的欢迎
'session' is referenced directly or indirectly in its own type annotation.

实现此目的的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

因此,查看express-session类型声明,它在Session命名空间下声明了Request(和修改后的Express对象)。使用这个我们可以创建一个类型声明(mySession.dt.s)来扩充默认属性,绕过声明合并的限制:

import {Express} from 'express';
import 'express-session';

declare module 'express' {
    export interface Request {
        session: Express.Session & {
            myOwnData: string;
            myOwnData2: number;
            myOwnData3: boolean;
        };
    }
}

请注意,编译器似乎对此文件中的导入有一定的灵活性(如果导入ExpressRequest似乎并不关心),但显式是最大的是一致的。

然后我们可以将此声明导入我们的服务器文件:

import express = require('express');
import {Express, Request, Response} from 'express';
import './mySession';
import * as session from 'express-session';

const app: Express = express();
const PORT = process.env.PORT || process.env.NODE_PORT || 3000;

app.use('/endpoint', (req: Request, res: Response) => {
   const a: number = req.session.myOwnData3 + 2; // fails to compile and highlighted by editors
   console.log(req.session.myOwnData); // compiles and provided autocomplete by Webstorm
   // do stuff
   return res.ok();
});

app.use(session(/** do session stuff **/));

log.info(`Start Express Server on ${PORT}`);
app.listen(PORT);

经过测试,此结构在添加的属性上实现了类型安全性,并在VSCode和WebStorm中同时使用express-session和添加的属性实现智能感知/自动完成。

不幸的是,正如您所指出的,在使用类型推断的情况下,这不会全局应用(仅限于您明确导入Request的地方)。如果您想完全控制界面,可以卸载@types/express-session并复制&修改d.ts(并导入)。另一种可能性是宣布一个全新的财产和实施,但显然还有更多的工作。