Typescript整合passport等库时的类型合并错误求助
TypeScript中Passport类型声明合并失效问题排查与解决
我在TypeScript中使用passport、passport-local和express-session,已安装@types/passport、@types/express-session、@types/passport-local及@types/express依赖,计划用connect-redis存储会话。目前遇到两个类型错误:
Property 'emailVerified' does not exist on type 'User'Property 'id' does not exist on type 'User'
尝试用声明合并解决但无效,以下是我的相关代码文件:
tsconfig.json
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "typeRoots": ["./node_modules/@types"] }, "include": ["src/**/*"] }
src/@types/express/index.d.ts
declare namespace Express { interface User { id: string; emailVerified: boolean; } }
passport.ts
import passport from 'passport'; import { Strategy as LocalStrategy } from 'passport-local'; import UserModel from '../models/user'; passport.use( new LocalStrategy(async (username, password, done) => { try { const user = await UserModel.findOne({ username }); if (!user) return done(null, false); const isValid = await user.comparePassword(password); if (!isValid) return done(null, false); return done(null, user); } catch (err) { return done(err); } }) ); passport.serializeUser((user, done) => { done(null, user.id); // 报错:Property 'id' does not exist on type 'User' }); passport.deserializeUser(async (id, done) => { try { const user = await UserModel.findById(id); done(null, user); } catch (err) { done(err); } }); export default passport;
auth.controller.ts
import { Request, Response } from 'express'; export const getProfile = (req: Request, res: Response) => { // 报错:Property 'emailVerified' does not exist on type 'User' if (req.user?.emailVerified) { res.json(req.user); } else { res.status(403).json({ message: 'Email not verified' }); } };
问题原因
- tsconfig类型路径配置缺失:默认
typeRoots只包含node_modules/@types,TypeScript无法识别自定义的src/@types目录下的声明文件。 - 声明合并语法不规范:自定义
Express.User时未用global命名空间包裹,导致无法正确合并内置类型。 - Passport序列化/反序列化未指定类型:未明确
user参数的类型,TypeScript无法关联到自定义的User类型。
解决方法
1. 修正tsconfig.json的typeRoots配置
添加自定义类型目录到typeRoots,确保TypeScript能识别:
{ "compilerOptions": { // 其他配置不变 "typeRoots": ["./src/@types", "./node_modules/@types"] } }
2. 调整自定义声明文件的写法
修改src/@types/express/index.d.ts,用global命名空间包裹并导出空对象:
declare global { namespace Express { interface User { id: string; emailVerified: boolean; // 补充你需要的其他用户属性 } } } // 必须导出空对象,标记为模块 export {};
3. 为Passport的序列化/反序列化指定类型
在passport.ts中明确user的类型为Express.User:
passport.serializeUser((user: Express.User, done) => { done(null, user.id); }); passport.deserializeUser(async (id: string, done) => { try { const user = await UserModel.findById(id); done(null, user as Express.User); // 若模型返回类型不匹配,可断言类型 } catch (err) { done(err); } });
4. 验证类型关联
重启TypeScript服务(或编辑器的TS语言服务),检查错误是否消失。如果仍有问题,确认:
- 自定义声明文件的路径正确(
src/@types/express/index.d.ts是标准路径) - 所有
@types依赖版本与对应库版本兼容,可尝试重新安装依赖:
rm -rf node_modules package-lock.json npm install
内容的提问来源于stack exchange,提问作者PirateApp
相关产品推荐
相关产品推荐

