[英]Unable to extend Express Request in TypeScript
這個問題已被問過幾次,但給出的答案都沒有對我有用。 我正在嘗試擴展 Express Request
對象以包含一個屬性來存儲User
對象。 我創建了一個聲明文件express.d.ts
,並將它放在與我的tsconfig.json
相同的目錄中:
import { User } from "./src/models/user";
declare namespace Express {
export interface Request {
user: User;
}
}
然后我嘗試在secured-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;
~~~~
我的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
我在這里做錯了什么?
問題是,你是不是增強了Express
通過定義全局命名空間中express
你的模塊中創建一個新的命名空間(一旦你使用了一個文件變成一個模塊import
)。
解決方法是在global
聲明命名空間
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;
}
}
我有同樣的問題...
你不能只使用擴展請求嗎? 喜歡:
interface RequestWithUser extends Request {
user?: User;
}
router.post('something',(req: RequestWithUser, res: Response, next)=>{
const user = req.user;
...
}
另一方面,如果您在 express 中使用異步回調,請確保使用 express-async 包裝器或確保您確切知道自己在做什么。 我推薦: awaitjs
我嘗試了很多解決方案,但沒有一個奏效。
但它也可以如此簡單並且完美運行。 當然,您可以將 AuthenticatedRequest 保存在其他任何地方。
import { IUser } from './src/_models/user.model';
export interface AuthenticatedRequest extends Request {
user: IUser;
}
static async getTicket(req: AuthenticatedRequest, res: Response){}
更新:
所以我從這里發現了一些有趣的東西: Import class in definition file (*d.ts) 。
聲明命名空間 Express 應該是打字稿的第一行,將其視為全局
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;
}
}
對我來說,我只是在偷懶。
import { User } from '../database/models/user';
router.use(async (req, res, next) => {
const user = req.user as User;
// ...
});
0
聲明合並意味着編譯器將兩個單獨聲明的同名聲明合並為一個定義。
請參閱下面的示例,其中接口聲明在打字稿中合並
interface Boy {
height: number;
weight: number;
}
interface Boy {
mark: number;
}
let boy: Boy = {height: 6 , weight: 50, mark: 50};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.