我是 TypeScript 新手,我在一个只是为了练习而制作的小应用程序中使用 Passport.js 实现了用户身份验证。
问题
我试图告诉 Passport.js 将用户属性
id
保存到会话中以进行进一步身份验证,但我只是找不到一种方法来告诉 TypeScript id
的属性 user
实际上存在。
passport.serializeUser((user, done) => {
done(undefined, user.id); // Property 'id' does not exists on type 'User'
});
参数
user
显示为类型 Express.User
,但它实际上是 TypeOrm 实体 User
的实例。通过搜索帖子,我发现我可以扩展类型Express.User
来添加我需要使用的属性:
// src/custom-typings/index.d.ts
namespace Express {
interface User {
id?: number;
}
}
这样做可以消除编码时的错误警告,但是当我尝试编译代码时,错误再次出现,但在我的 VSCode 终端中!。
src/core/passport.ts:38:24 - error TS2339: Property 'id' does not exist on type 'User'.
38 done(undefined, user.id);
~~
at createTSError (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:513:12)
at reportTSError (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:517:19)
at getOutput (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:752:36)
at Object.compile (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:968:32)
at Module.m._compile (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:1056:42)
at Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
at Object.require.extensions.<computed> [as .ts] (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:1059:12)
at Module.load (internal/modules/cjs/loader.js:985:32)
at Function.Module._load (internal/modules/cjs/loader.js:878:14)
at Module.require (internal/modules/cjs/loader.js:1025:19)
我确实将自定义类型添加到了 tsconfig.json 中:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["es6"],
"outDir": "dist",
"rootDir": "src",
"strict": true,
"typeRoots": ["./src/custom-typings", "./node_modules/@types"],
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
这是我的项目结构:
.
├── src
│ ├── core
│ │ └── passport.ts
│ │
│ │
│ ├── custom-typings
│ │ └── index.d.ts
│ │
│ └── other stuff
│
│
├── tsconfig.json
所有其他解决方案都说这是解决这个典型问题的方法,但我就是无法使其工作,我错过了什么?.
使用模型中定义的 User 类,而不是应该有 id 的类。您还可以将 id 替换为用户类型中的任何其他唯一标识符。
passport.serializeUser((user: User, done) => {
done(undefined, user.id);
});
将任何“类型”传递给用户属性
passport.serializeUser((user:any, done)=>{
done(null, user.id)
})
希望这有帮助
问题是 Passport 的 serializeUser 和 deserializeUser 方法期望用户对象类型与 Passport 使用的类型匹配,但 TypeScript 推断 UserInterface 与 User 不匹配。出现这种差异的原因是 TypeScript 不会自动识别 Mongoose 模型来扩展 UserInterface。 要解决此问题,您可以在serializeUser 和deserializeUser 方法内将用户对象显式转换为UserInterface。这种方法确保 TypeScript 理解传递的用户对象与预期的接口相匹配。
passport.serializeUser((user, done) => {
done(null, (user as UserInterface)._id);
});
// 这将根据存储在会话对象中的会话 ID 获取会话对象。
passport.deserializeUser((_id: string, done) => {
User.findById(_id, (err: Error, user: UserInterface | null) => {
done(err, user);
});
});
@types/passport
npm install --save @types/passport
index.d.ts
文件后,在声明全局函数中有一个接口User对象。只需在其中添加您想要的任何变量即可,例如
declare global {
namespace Express {
// tslint:disable-next-line:no-empty-interface
interface AuthInfo {}
// tslint:disable-next-line:no-empty-interface
interface User {
*username:string;
yourVariable: any;
id:number; etc*
}
}
}