简体   繁体   English

Typescript 错误:属性“用户”在类型“请求”上不存在

[英]Typescript Error: Property 'user' does not exist on type 'Request'

I have the following piece of code in my express app我的快递应用程序中有以下代码

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

and my IDE seems to be complaining with the error我的 IDE 似乎在抱怨错误

error TS2339: Property 'user' does not exist on type 'Request'.错误 TS2339:类型“请求”上不存在属性“用户”。

When I compile my typescript code it seems to be throwing this error.当我编译我的 typescript 代码时,它似乎抛出了这个错误。 Any ideas why this is happening?任何想法为什么会这样?

We have a large API written in Express and Typescript, and this is how we handle such scenarios:我们有一个用 Express 和 Typescript 编写的大型 API,这就是我们处理此类场景的方式:

We keep the request definitions in one file:我们将请求定义保存在一个文件中:

import { Request } from "express"
export interface IGetUserAuthInfoRequest extends Request {
  user: string // or any other type
}

And then in the file where we are writing the controller functions:然后在我们编写 controller 函数的文件中:

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
});

Be advised that "user" is not a property that is available natively in the Request object of Express.请注意,“用户”不是 Express 的请求 object 中本机可用的属性。 Make sure that you are using a middleware that adds such property to the request object.确保您使用的中间件将此类属性添加到请求 object。

req is probably of type Request from "express" package and user does not exist there. req 可能是来自“express”package 的 Request 类型,并且用户在那里不存在。 You have to either extend Request with own router handler or cast it to type any or object.您必须使用自己的路由器处理程序扩展请求或将其强制转换为任何类型或 object。

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

You may also use module/global augmentation您也可以使用模块/全局扩充

import { Request } from "express"

declare module "express" { 
  export interface Request {
    user: any
  }
}

newer express definition may need to augment the core def instead较新的 express 定义可能需要增加核心 def

declare module 'express-serve-static-core' {
  export interface Request {
    user: any
  }
}

You can also make your own handler wrapper (instead of extending Router functionality in ExpressJs).您还可以制作自己的处理程序包装器(而不是在 ExpressJs 中扩展路由器功能)。

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);
}));

UPDATED: Since Typescript is evolving I would also consider using Type Guards更新:由于 Typescript 正在发展,我也会考虑使用Type Guards

if (hasUser(req)) {
    console.log(req.user)
}

function hasUser(request: Request): request is Request & { user: number } {
    return 'user' in request && typeof request['user'] == 'number'
}

You need to make a Declaration Merging:您需要进行声明合并:

"Declaration merging means that the compiler merges two separate declarations declared with the same name into a single definition." “声明合并意味着编译器将两个使用相同名称声明的单独声明合并到一个定义中。”

To do that you can create a file called types.d.ts at your project src folder (or wherever you want) with the following content:为此,您可以在项目 src 文件夹(或任何您想要的位置)中创建一个名为 types.d.ts 的文件,其中包含以下内容:

declare namespace Express {
  export interface Request {
      user: any;
  }
  export interface Response {
      user: any;
  }
}

Here we are telling the compiler to add user propertie to our Request and Response definiton.在这里,我们告诉编译器将用户属性添加到我们的请求和响应定义中。

Next, we need to attach this to our tsconfig.json.接下来,我们需要将其附加到我们的 tsconfig.json。

Example:例子:

{
  "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"]
}

Now, the typescript compiler know that Request, which has a property called user that in my case, can accept any json object.现在,typescript 编译器知道 Request,它有一个名为 user 的属性,在我的例子中,它可以接受任何 json object。 You can restrict the type for string if you want.如果需要,您可以限制字符串的类型。

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

You're getting this error because there's no type definition for the user property in the the native express Request object.您收到此错误是因为本机express Request object 中的user属性没有类型定义。 You should install the type definitions for the middleware you're using to add user to the request.您应该为用于将user添加到请求的中间件安装类型定义。

For example, if you're using the passport library for JWT authentication as middleware:例如,如果您使用 JWT 身份验证的passport库作为中间件:

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);}
    ...
    ...

You should add the type definitions for passport :您应该添加passport的类型定义:

npm install --save @types/passport
  1. create new folder named types inside "src" folder在“src”文件夹中创建名为types的新文件夹
  2. create file <filename>.d.ts in types foldertypes文件夹中创建文件<filename>.d.ts
  3. add following code:添加以下代码:
declare namespace Express {
  export interface Request {
    user: any
  }
}
  • you will notice that error disappeared你会注意到错误消失了
  1. inside section typeRoots add the following to tsconfig.json file:typeRoots部分内,将以下内容添加到tsconfig.json文件中:
"typeRoots": [
      "./node_module/@types",
      "./src/types"
],
  • you can use type Request of express like this:您可以像这样使用 express 类型的Request
import { Request, Response } from "express";
router.get('/auth/userInfo', this.validateUser,  (req: Request, res: Response) => {
    res.json(req.user);
});
  • if you use ts-node you will get the same error when you try to execute your .ts file because ts-node ignore .d.ts fies unless you add flag --files to package.json script like this:如果您使用 ts-node ,当您尝试执行您的.ts文件时,您将收到相同的错误,因为 ts-node 忽略.d.ts文件,除非您将标志--files添加到package.json脚本,如下所示:
"scripts": {
    .
    .
    "dev": "ts-node --files src/app.ts"
  }
  • for more about this topic you can see this repository that created by Microsoft team.有关此主题的更多信息,您可以查看 Microsoft 团队创建的这个存储库

If you're using ts-node and not ts-node-dev , do this:如果您使用的是ts-node而不是ts-node-dev ,请执行以下操作:

  1. Create a typings folder in your src folder.在您的src文件夹中创建一个typings文件夹。
  2. Create a folder within the typings folder with the name of the package you intend to extend.typings文件夹中创建一个文件夹,其名称为您打算扩展的package
  3. Create an index.d.ts file with the new folder.使用新文件夹创建一个index.d.ts文件。

In my case, I am extending express , I ended up with something like this:就我而言,我正在扩展express ,我最终得到了这样的结果:

  src/
    - typings/
      - express/
        - index.d.ts

within the index.d.ts file I have this:index.d.ts文件中我有这个:

declare module Express {
    export interface Request {
        bucketUrl: string;
        fileName: string;
    }
}

Remember to update your .tsconfig :请记住更新您的.tsconfig

{
  "compilerOptions": {
    "typeRoots" : ["./node_modules/@types", "./typings"]
  }
}

For people using GraphQL, there comes a problem with the graphqlExpress function not accepting your new interface .对于使用 GraphQL 的人来说, graphqlExpress function 不接受您的新interface存在问题。 I was attempting to followthis guide until I ran into this exact problem.我一直在尝试遵循本指南,直到遇到这个确切的问题。 I have figured out this solution:我想出了这个解决方案:

this.app.use("/graphql", bodyParser.json(), this.auth, graphqlExpress((req: AuthRequest | undefined) => ({ 
    schema,
    context: {
        user: req!.user
    }
})));

And in the AuthRequest interface:AuthRequest接口中:

import {Request} from "express"

export interface AuthRequest extends Request {
    user?: string
}

Typescript will not allow you to use AuthRequest unless it is also allowed to be undefined. Typescript 将不允许您使用 AuthRequest,除非它也允许未定义。 Therefore the | undefined因此| undefined | undefined . | undefined ( source ) 来源

After this point, the user object does not 100% exist on the Request object, hence the?在此之后,用户 object 不会 100% 存在于请求 object 上,因此? after user.在用户之后。

In my case, using ?就我而言,使用? to solve the problem.解决问题。

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)
});

Just extend "Request" without declaration.只需扩展“请求”而不进行声明。

I was using okta-angular-node with express for this https://developer.okta.com/blog/2018/10/30/basic-crud-angular-and-node我为此https://developer.okta.com/blog/2018/10/30/basic-crud-angular-and-node使用 okta-angular-node 和 express

I came up with similar error for req.user .我为req.user想出了类似的错误。 Please check the server/auth.ts inside the above given link.请检查上面给出的链接中的 server/auth.ts。

Type casting worked for me.类型转换对我有用。 Try to cast as follows尝试按如下方式投射

req.user to (req['user']) req.user(req['user'])

Add a typeRoots to your tsconfig.json , this will tell typescript where to look to find declaration files .typeRoots添加到您的tsconfig.json中,这将告诉 typescript 在哪里查找声明文件 By default typescript looks in /node_modules/@types , but when you specify this property, those defaults are cleared.默认情况下 typescript 在/node_modules/@types中查找,但是当您指定此属性时,这些默认值将被清除。 You can read more here .你可以在这里阅读更多。

tsconfig.json tsconfig.json

{
  "compilerOptions": {
    "typeRoots": ["./node_modules/@types", "./src/util"]
  }
}            

types.d.ts类型.d.ts

import { User } from '../models/user'

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

Folder structure文件夹结构

node_modules
tsconfig.json
/src/
   /models/
      user.ts
   /util/
      types.d.ts

You can try including the below snippet in your middleware.ts file:您可以尝试在 middleware.ts 文件中包含以下代码段:

 declare module 'express-serve-static-core' { interface Request { user?: string } }

declare global {
  namespace Express {
    interface Request {
      user?: any
    }
  }
}

Old question but if anyone stumbles across this like I did, take a look at 'Declaration Merging' - solved the issue for me.老问题,但如果有人像我一样偶然发现这个问题,请查看“声明合并” - 为我解决了这个问题。

https://www.typescriptlang.org/docs/handbook/declaration-merging.html https://www.typescriptlang.org/docs/handbook/declaration-merging.html

https://truetocode.com/extend-express-request-and-response-typescript-declaration-merging/ https://truetocode.com/extend-express-request-and-response-typescript-declaration-merging/

You need to decorate the request using fastify decorators as mentioned below,你需要使用下面提到的 fastify 装饰器来装饰请求,

fastify.decorateRequest('user', <pass null or empty string here>)

and handle what should be in the user object.并处理用户 object 中应该包含的内容。

Official document - https://www.fastify.io/docs/latest/Decorators/官方文档-https://www.fastify.io/docs/latest/Decorators/

I recently had the same issue, I followed the solution in the previous comments and this repo and I still had the same issue.我最近遇到了同样的问题,我按照之前评论和这个 repo 中的解决方案,我仍然遇到同样的问题。 After doing more digging it seems like it's a bug with ts-node.在进行更多挖掘之后,它似乎是 ts-node 的一个错误。

To solve this you need to run your server with a --files flag要解决这个问题,您需要使用 --files 标志运行您的服务器

So if you normally run your server ts-node ./src/server.ts or nodemon ./src/server.ts Change it to ts-node --files ./src/server.ts or nodemon --files ./src/server.ts因此,如果您通常运行服务器 ts-node ./src/server.ts 或 nodemon ./src/server.ts 将其更改为 ts-node --files ./src/server.ts 或 nodemon --files ./src /server.ts

After that, I was able to get rid of both the VScode errors and errors while starting the server.之后,我能够在启动服务器时摆脱 VScode 错误和错误。

Because the "user" property doesn't exist in the native express "Request" object.因为“用户”属性在本机快递“请求”object 中不存在。

There are various workarounds for this issue.此问题有多种解决方法。

1- Simplest one -... as any 1-最简单的一个-...

router.get('/auth/userInfo', this.validateUser,  (req, res) => {
    res.json((req as any).user);
})

2- Add the following code to the app.js or interface file once. 2-将以下代码添加到app.js或接口文件一次。

    declare module "express-serve-static-core" {
       interface Request {
           user: any;
       }
    }

in my case I had to do this就我而言,我必须这样做

interface RequestUserAuth extends Request {
user?: {
    id: string
    role: string
    // or any type you want but you must to use it like that "user?: etc..."
   }
}

    app.get('/', auth, (req: RequestUserAuth, res: Response) => {
    console.log(req.user)  
   })

Just do做就是了

import { Request, Response} from "express";

then do this;然后这样做;

router.get('/auth/userInfo', this.validateUser, (req:any, res:Response) => { res.json(req.user); });

I had a working index.d.ts using other tips here but the fact that it was in the same folder as an unrelated index.ts was causing it to not work.我有一个工作 index.d.ts 使用这里的其他提示,但事实上它与不相关的 index.ts 在同一个文件夹中导致它无法工作。 I moved index.d.ts to its own types folder and the types started to get used.我将 index.d.ts 移动到它自己的类型文件夹中,这些类型开始被使用。 I'm guessing there was a collision with index.ts being at the same level.我猜与 index.ts 处于同一级别发生了冲突。

Just going to share my types/index.d.ts in case it helps someone who is also using Prisma只是分享我的 types/index.d.ts 以防它帮助那些也在使用 Prisma 的人

import { User as PrismaUser } from "../prisma/prismaclient";

declare module "passport" {
  namespace Express {
    interface User extends PrismaUser {}
  }
}

declare module 'express-serve-static-core' {
  interface Request {
    user?: PrismaUser
  }
  interface Response {
    user?: PrismaUser
  }
}


declare module "express-session" {
  interface SessionData {
    user: PrismaUser;
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Express + Typescript:“请求”类型上不存在属性“正文” - Express + Typescript: Property 'body' does not exist on type 'Request' TypeScript 错误 TS2339:类型“用户”上不存在属性“id” - TypeScript error TS2339: Property 'id' does not exist on type ' User' 带有 Passport 和 Typescript 的“用户”类型上不存在属性“id” - Property 'id' does not exist on type 'User' with Passport and Typescript Express typescript 中的“typeof db”类型不存在属性“用户” - Property 'User' does not exist on type 'typeof db' sequelize in express typescript TypeScript 给我一个属性在类型响应上不存在的错误 - TypeScript gives me an error of Property Does Not Exist on Type Response 打字稿错误:量角器中的“未知”类型不存在“清除”或“发送”属性 - Typescript error: Property 'clear' or 'send' does not exist on type 'unknown' in protractor Typescript编译错误:类型&#39;typeof e&#39;不存在属性&#39;bodyParser&#39; - Typescript compile error: Property 'bodyParser' does not exist on type 'typeof e' (Typescript)属性“ window”在类型“ Global”上不存在 - (Typescript) Property 'window' does not exist on type 'Global' Typescript 类型“字符串”上不存在属性“标签” - Typescript Property 'label' does not exist on type 'string Typescript 向错误 object 添加属性时出错“属性...在类型‘错误’上不存在” - Typescript error when adding property to Error object "Property ... does not exist on type 'Error'"
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM