当前位置: 首页 > 知识库问答 >
问题:

无法在TypeScript中扩展Express Request

聂昱
2023-03-14

这个问题已经被问了好几次了,但没有一个答案对我有效。我试图扩展Express请求对象,使其包含一个属性来存储用户对象。我创建了一个声明文件,express。d、 并将其放置在与我的配置相同的目录中。json:

import { User } from "./src/models/user";

declare namespace Express {
    export interface Request {
        user: User;
    }
}

然后我尝试在安全api中对其进行赋值。ts:

import express from 'express';
import { userService } from '../services/user';

router.use(async (req, res, next) => {
    try {
        const user = await userService.findByUsername(payload.username);

        // do stuff to user...

        req.user = user;
        next();
    } catch(err) {
        // handle error
    }
});

我得到以下错误:

src/routes/secured-api.ts:38:21 - error TS2339: Property 'user' does not exist on type 'Request'.

38                 req.user = user;
                       ~~~~

我的用户是:

import { Model, RelationMappings } from 'objection';

export class User extends Model {

    public static tableName = 'User';
    public static idColumn = 'username';

    public static jsonSchema = {
        type: 'object',
        required: ['fname', 'lname', 'username', 'email', 'password'],

        properties: {
            fname: { type: 'string', minLength: 1, maxLength: 30 },
            lname: { type: 'string', minLength: 1, maxLength: 30 },
            username: { type: 'string', minLength: 1, maxLength: 20 },
            email: { type: 'string', minLength: 1, maxLength: 320 },
            password: { type: 'string', minLength: 1, maxLength: 128 },
        }
    };

    public static modelPaths = [__dirname];

    public static relationMappings: RelationMappings = {

    };

    public fname!: string;
    public lname!: string;
    public username!: string;
    public email!: string;
    public password!: string;
}

我的tsconfig.json是:

{
    "compilerOptions": {
      "target": "es6",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
      "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
      "lib": ["es2015"],                             /* Specify library files to be included in the compilation. */
      "outDir": "./build",                      /* Redirect output structure to the directory. */
      "strict": true,                           /* Enable all strict type-checking options. */
      "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    }
}

我的目录结构是:

backend/
    package.json
    tsconfig.json
    express.d.ts
    src/
        models/
            user.ts
        routes/
            secured-api.ts

我做错了什么?


共有3个答案

周鸿光
2023-03-14

我尝试了很多解决方案,但都不起作用。

但它也可以这么简单,而且工作得很完美。当然,您可以将AuthenticatedRequest保存到其他任何地方。

import { IUser } from './src/_models/user.model';

export interface AuthenticatedRequest extends Request {
  user: IUser;
}
static async getTicket(req: AuthenticatedRequest, res: Response){}

更新:

所以我在这里发现了一些有趣的东西:在定义文件(*d.ts)中导入类。

declare namespace Express应该是typescript的第一行,并将其计算为全局

declare namespace Express {

  interface Request {
    user: import('./src/modules/models/user.model').IUser;
    uploadedImage: { key: string; type: string };
    group: import('./src/modules/models/group.model').IGroup;
  }
}
何琨
2023-03-14

我也有同样的问题。。。

你不能只使用扩展请求吗?比如:

interface RequestWithUser extends Request {
    user?: User;
}
router.post('something',(req: RequestWithUser, res: Response, next)=>{
   const user = req.user;
   ...
}

另一方面,如果您在express中使用异步回调,请确保使用express async wrappers或确保您确切知道自己在做什么。我推荐:awaitjs

宋经业
2023-03-14

问题是,您没有扩展由Express定义的全局命名空间,而是在模块中创建了一个新的命名空间(一旦您使用导入,该文件就会成为一个模块)。

解决方案是在全局中声明名称空间

import { User } from "./src/models/user";

declare global {
    namespace Express {
        export interface Request {
            user: User;
        }
    }
}

或者不使用模块导入语法,只需引用类型:

declare namespace Express {
    export interface Request {
        user: import("./src/models/user").User;
    }
}
 类似资料:
  • 问题内容: 我正在将React.js与TypeScript一起使用。有什么方法可以创建从其他组件继承但具有一些其他道具/状态的React组件? 我想要达到的目标是这样的: 但是,如果我把这个会失败中,我得到一个错误的打字稿(类型的参数是不能分配给类型)。我想这不是TypeScript专用的东西,而是将继承与泛型(?)混合使用的一般限制。是否有任何类型安全的解决方法? 更新 我选择的解决方案(基于D

  • 是否有可能在这个答案中提供等效的内容,但在TypeScript中? 对 Java 生成器类进行子类化 这是迄今为止我对基类的了解: 和扩展类: 正如另一个线程提到的,由于上下文的变化,我将无法按此顺序构建客户: 我目前正在尝试使用泛型来解决此问题,但是在为我的 setter 方法返回 this 指针时遇到问题(类型 this 不能分配给类型 T)。有什么想法吗?

  • 我有一个节点。js应用程序,将一些配置信息附加到对象: TypeScript 编译器不喜欢这样,因为 类型没有名为 的对象: TS2339:类型“Global”上不存在属性“myConfig”。 我不想这样做: 我如何扩展< code>Global类型以包含< code>myConfig或者只是告诉TypeScript闭嘴并相信我?我更喜欢第一个。 我不想更改中的声明。我看到了这篇SO帖子,并尝试

  • 问题内容: 我有一个node.js应用程序,该应用程序将一些配置信息附加到该对象: TypeScript编译器不喜欢这样,因为该类型没有名为的对象: TS2339:类型“ Global”上不存在属性“ myConfig”。 我不想这样做: 如何扩展类型以包含或只是告诉TypeScript关闭并信任我?我希望第一个。 我不想更改其中的声明。我看到了这样的帖子,并尝试了这个: 作为扩展现有接口的一种方

  • 我想创建如下界面: 然后我们可以将它用于一个新类: 我想对s做同样的事情。在纯JavaScript中,我可以使类型,例如,满足以下接口: 但TypeScript不允许我这样做: 有办法做到这一点吗?

  • 类和的行为有何不同?我为什么要选择其中一个? (目前,TypeScript手册和语言规范不包括抽象类。)