我的快递应用程序中有以下代码
router.get('/auth/userInfo', this.validateUser, (req, res) => {
res.json(req.user);
});
我的IDE似乎在抱怨错误
错误TS2339:“请求”类型中不存在属性“用户”。
当我编译我的打字稿代码时,它似乎抛出了这个错误。任何想法为什么会这样?
答案 0 :(得分:15)
我们有一个用Express和Typescript编写的大型API,这就是我们处理这种情况的方法:
我们将请求定义保存在一个文件中:
import { Request } from "express"
export interface IGetUserAuthInfoRequest extends Request {
user: string // or any other type
}
然后在我们编写控制器功能的文件中:
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
});
请注意,“user”不是Express的Request对象中本机可用的属性。确保您使用的是将此类属性添加到请求对象的中间件。
答案 1 :(得分:5)
req可能是来自“express”包的类型Request,用户在那里不存在。您必须使用自己的路由器处理程序扩展Request或将其强制转换为any或object。
尝试res.json(req['user'])
或res.json( (<any>req).user )
您也可以使用模块/全局扩充
declare module "express" { // declare module "express-serve-static-core"
export interface Request {
user: any
}
}
您也可以创建自己的处理程序包装器(而不是在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);
}));
答案 2 :(得分:4)
您收到此错误,因为在本机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);}
...
...
您应该为passport
添加类型定义:
npm install --save @types/passport
答案 3 :(得分:3)
您需要进行声明合并:
“声明合并意味着编译器将两个单独的合并 以相同名称声明的声明将成为一个定义。”
为此,您可以在项目src文件夹(或所需位置)中创建一个名为type.d.ts的文件,其内容如下:
declare namespace Express {
export interface Request {
user: any;
}
export interface Response {
user: any;
}
}
在这里,我们告诉编译器将用户属性添加到我们的“请求和响应”定义中。
下一步,我们需要将此附加到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"]
}
现在,打字稿编译器知道Request拥有一个名为user的属性,在我的情况下可以接受任何json对象。您可以根据需要限制字符串的类型。
答案 4 :(得分:2)
对于使用GraphQL的人来说,graphqlExpress
函数存在一个问题,即不接受您的新interface
。我一直尝试遵循this guide,直到遇到这个确切的问题。我已经找到了解决方案:
this.app.use("/graphql", bodyParser.json(), this.auth, graphqlExpress((req: AuthRequest | undefined) => ({
schema,
context: {
user: req!.user
}
})));
在AuthRequest
界面中:
import {Request} from "express"
export interface AuthRequest extends Request {
user?: string
}
Typescript将不允许您使用AuthRequest,除非也允许对其进行未定义。因此,| undefined
。 (source)
在这一点之后,用户对象在请求对象上不存在100%,因此?在用户之后。
答案 5 :(得分:1)
为此https://developer.okta.com/blog/2018/10/30/basic-crud-angular-and-node我在okta-angular-node中使用了
我为req.user
遇到了类似的错误。请检查上面给定链接中的服务器/身份验证。
类型转换对我有用。尝试进行如下投射
req.user
至(req['user'])
答案 6 :(得分:1)
如果您使用的是 ts-node
而不是 ts-node-dev
,请执行以下操作:
typings
文件夹中创建一个 src
文件夹。typings
文件夹中创建一个文件夹,名称为您要扩展的 package
。index.d.ts
文件。就我而言,我扩展了 express
,结果是这样的:
src/
- typings/
- express/
- index.d.ts
在 index.d.ts
文件中我有这个:
declare module Express {
export interface Request {
bucketUrl: string;
fileName: string;
}
}
记得更新您的.tsconfig
:
{
"compilerOptions": {
"typeRoots" : ["./node_modules/@types", "./typings"]
}
}
答案 7 :(得分:0)
将 typeRoots
添加到您的 tsconfig.json
,这将告诉打字稿在哪里寻找 declaration files。默认情况下,打字稿在 /node_modules/@types
中查找,但是当您指定此属性时,这些默认值将被清除。您可以阅读更多here。
tsconfig.json
{
"compilerOptions": {
"typeRoots": ["./node_modules/@types", "./src/util"]
}
}
types.d.ts
import { User } from '../models/user'
declare global {
namespace Express {
interface Request {
user: User
}
}
}
文件夹结构
node_modules
tsconfig.json
/src/
/models/
user.ts
/util/
types.d.ts
答案 8 :(得分:0)
您需要使用下面提到的 fastify 装饰器来装饰请求,
fastify.decorateRequest('user', <pass null or empty string here>)
并处理用户对象中应该包含的内容。
答案 9 :(得分:0)
您可以尝试在 middleware.ts 文件中包含以下代码段:
declare module 'express-serve-static-core' {
interface Request {
user?: string
}
}
答案 10 :(得分:-1)
一个老问题,但是如果有人像我一样偶然发现这个问题,请看一下“声明合并”,为我解决了这个问题。
https://www.typescriptlang.org/docs/handbook/declaration-merging.html
https://truetocode.com/extend-express-request-and-response-typescript-declaration-merging/