扩展@types 声明上的现有属性

its*_*ned 5 typescript typescript-typings

我正在尝试扩展express.Request上可用的expressRequest对象,以便它在会话中包含一些其他数据。我尝试创建自己的类型文件(d.ts)并使用以下代码:

import * as express from 'express';

declare module 'express' {
    export interface Request {
        session: express.Request['session'] & {
            myOwnData: string;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误

'session' is referenced directly or indirectly in its own type annotation.
Run Code Online (Sandbox Code Playgroud)

实现这一点的正确方法是什么?

Gre*_*ycz 4

因此,查看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;
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,编译器似乎对此文件中的导入有些灵活(就像它似乎不关心或Express是否Request被导入一样),但显式的将是最一致的。

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

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);
Run Code Online (Sandbox Code Playgroud)

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

不幸的是,正如您所指出的,这不会在使用类型推断的情况下全局应用(仅在您显式 import 的情况下Request)。如果您想完全控制界面,您可以卸载@types/express-session并复制并修改 d.ts(然后导入)。另一种可能性是声明一个全新的属性并实施,但显然需要更多的工作。