打字稿错误:"请求"类型中不存在属性"用户"

RRP*_*RRP 16 node.js typescript

我在我的快递应用程序中有以下代码

router.get('/auth/userInfo', this.validateUser,  (req, res) => {
    res.json(req.user);
});
Run Code Online (Sandbox Code Playgroud)

我的IDE似乎抱怨错误

错误TS2339:"请求"类型中不存在属性"用户".

当我编译我的打字稿代码时,它似乎抛出了这个错误.任何想法为什么会这样?

Aks*_*tel 22

我们有一个用Express和Typescript编写的大型API,这就是我们处理这些场景的方法:

我们将请求定义保存在一个文件中:

import { Request } from "express"
export interface IGetUserAuthInfoRequest extends Request {
  user: string // or any other type
}
Run Code Online (Sandbox Code Playgroud)

然后在我们编写控制器功能的文件中:

import { Response } from "express"
import { IGetUserAuthInfoRequest } from "./definitionfile"

app.get('/auth/userInfo', validateUser,  (req: IGetUserAuthInfoRequest, res: Response) => {
  res.status(200).json(req.user); // Start calling status function to be compliant with Express 5.0
});
Run Code Online (Sandbox Code Playgroud)

请注意,"user"不是Express的Request对象中本机可用的属性.确保您使用的是将此类属性添加到请求对象的中间件.

  • @roxxypoxxy 要修复“类型...的参数无法分配给类型...的参数”错误,请务必在“IGetUserAuthInfoRequest”中将“user”定义为可选,即使用“user?: string”而不是“user” : 字符串` (9认同)
  • 这给了我`类型'(req:ExtendedRequest,res:Response)=> Promise <void>'的参数不能分配给'Application'类型的参数。类型'(req:ExtendedRequest,res:Response)=> Promise <void>'从类型'Application'中缺少以下属性:init,defaultConfiguration,engine,set和其他62个。 (3认同)

Isl*_*her 18

  1. types在“src”文件夹中创建名为的新文件夹
  2. <filename>.d.tstypes文件夹中创建文件
  3. 添加以下代码:
declare namespace Express {
  export interface Request {
    user: any
  }
}
Run Code Online (Sandbox Code Playgroud)
  • 你会注意到错误消失了
  1. 在部分内typeRoots将以下内容添加到tsconfig.json文件中:
"typeRoots": [
      "./node_module/@types",
      "./src/types"
],
Run Code Online (Sandbox Code Playgroud)
  • 您可以使用Request这样的快递类型:
import { Request, Response } from "express";
router.get('/auth/userInfo', this.validateUser,  (req: Request, res: Response) => {
    res.json(req.user);
});
Run Code Online (Sandbox Code Playgroud)
  • 如果您使用 ts-node,当您尝试执行.ts文件时,您将收到相同的错误,因为 ts-node 会忽略.d.tsfies,除非您--filespackage.json脚本添加标志,如下所示:
"scripts": {
    .
    .
    "dev": "ts-node --files src/app.ts"
  }
Run Code Online (Sandbox Code Playgroud)
  • 有关此主题的更多信息,您可以查看Microsoft 团队创建的此存储库。


小智 12

您需要进行声明合并:

“声明合并意味着编译器将使用相同名称声明的两个单独声明合并为一个定义。”

为此,您可以在项目 src 文件夹(或您想要的任何位置)中创建一个名为 type.d.ts 的文件,其中包含以下内容:

declare namespace Express {
  export interface Request {
      user: any;
  }
  export interface Response {
      user: any;
  }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们告诉编译器将用户属性添加到我们的请求和响应定义中。

接下来,我们需要将它附加到我们的 tsconfig.json。

例子:

{
  "compilerOptions": {
      "module": "commonjs",
      "moduleResolution": "node",
      "pretty": true,
      "sourceMap": true,
      "target": "es6",
      "outDir": "./dist",
      "baseUrl": "./lib"
  },
  "include": [
      "lib/**/*.ts"
  ],
  "exclude": [
      "node_modules"
  ],
  "files":["types.d.ts"]
}
Run Code Online (Sandbox Code Playgroud)

现在,打字稿编译器知道 Request 有一个名为 user 的属性,在我的例子中可以接受任何 json 对象。如果需要,您可以限制字符串的类型。

最终的结果是,VSCode 没有错误 =)

  • 这应该是答案。 (7认同)

Los*_*lds 11

req可能是“ express”包中的Request类型,并且那里不存在用户。您必须使用自己的路由器处理程序扩展Request或将其强制转换为键入any或object。

尝试res.json(req['user'])res.json( (<any>req).user )

您也可以使用模块/全局扩充

import { Request } from "express"

declare module "express" { 
  export interface Request {
    user: any
  }
}
Run Code Online (Sandbox Code Playgroud)

您还可以制作自己的处理程序包装器(而不是扩展ExpressJs中的Router功能)。

import * as express from 'express';

interface IUserRequest extends express.Request {
    user: any
}

function myHandler(handler: (req: IUserRequest, res: express.Response, next?: express.NextFunction) => any) {
    return (req: express.Request, res: express.Response, next: express.NextFunction) => {
        try {

            validateUser(req, res, (err) => { // your validateUser handler that makes a user property in express Request
                if(err)
                     throw err;

                let requestWrapper: IUserRequest = <IUserRequest>req;

                handler(requestWrapper, res, next);
            })                
        }
        catch (ex) {
            next(ex);
        }
    } 
}

let app = express();
// init stuff for express but this.validateUser handler is not needed

app.use('/testuser', myHandler((req, res) => {
    res.json(req.user);
}));
Run Code Online (Sandbox Code Playgroud)


Tol*_*ide 8

如果您正在使用ts-node而不是ts-node-dev,请执行以下操作:

  1. typings在您的文件夹中创建一个文件夹src
  2. 在该文件夹中创建一个文件夹typings,名称为package您要扩展的文件夹。
  3. index.d.ts使用新文件夹创建文件。

就我而言,我正在扩展express,我最终得到了这样的结果:

  src/
    - typings/
      - express/
        - index.d.ts
Run Code Online (Sandbox Code Playgroud)

在文件中index.d.ts我有这个:

declare module Express {
    export interface Request {
        bucketUrl: string;
        fileName: string;
    }
}
Run Code Online (Sandbox Code Playgroud)

请记住更新您的.tsconfig

{
  "compilerOptions": {
    "typeRoots" : ["./node_modules/@types", "./typings"]
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 6

您收到此错误的原因user是本机express Request对象中没有属性的类型定义。您应该为要添加user到请求中的中间件安装类型定义。

例如,如果您将passport库用于JWT身份验证作为中间件:

router.get('/auth/userInfo', passport.authenticate('jwt', {session:false}), (req, res, next) => {
  // Get their info from the DB and return it
  User.findOne({ email: req.user.email }, (err, user) => {
    if (err) {return next(err);}
    ...
    ...
Run Code Online (Sandbox Code Playgroud)

您应该为添加类型定义passport

npm install --save @types/passport
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常快速的修复。谢谢。为我工作。 (4认同)

Jay*_* Lu 5

就我而言,使用?来解决问题。

import { Request } from "express";

interface MyUserRequest extends Request {
  // Use `user?:` here instead of `user:`.
  user?: string;
}

router.get('/auth/userInfo', (req: MyUserRequest, res) => {
  res.status(200).json(req.user)
});

Run Code Online (Sandbox Code Playgroud)

只需扩展“Request”而无需声明。