You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript+Express环境下Passport.js谷歌认证后无法获取displayName属性

问题原因分析

两个报错的根因如下:

  • 第一个错误Object is possibly 'undefined':TypeScript默认将req.user定义为可选类型,即使你加了登录校验中间件,TS也无法识别该中间件已经保证了req.user必然存在
  • 第二个错误Property 'displayName' does not exist on type 'User':@types/passport包默认定义的Express.User是空接口,没有包含谷歌OAuth返回的字段定义

解决步骤

步骤1:扩展Express.User类型定义

在你的项目中新建自定义类型声明文件,比如src/@types/express.d.ts,写入以下内容:

declare global {
  namespace Express {
    interface User {
      id: string;
      displayName: string;
      name: {
        familyName: string;
        givenName: string;
      };
      emails: { value: string; verified: boolean }[];
      photos: { value: string }[];
      provider: string;
      _json: Record<string, any>;
    }
  }
}
export {};

然后修改你的tsconfig.json,在compilerOptions配置项中加入自定义类型目录的识别:

{
  "compilerOptions": {
    // 其他原有配置保留
    "typeRoots": ["./node_modules/@types", "./src/@types"]
  }
}

注意:路径要和你存放express.d.ts的实际路径对应

步骤2:解决req.user可能为空的报错

因为你已经通过isLoggedIn中间件保证了访问/profile路由的用户必然已登录,req.user一定存在,所以可以直接用非空断言操作符!告诉TypeScript无需做空值校验:
修改你的路由代码:

app.get('/profile' ,isLoggedIn, (req: Request, res: Response)=> {
  res.send(`welcome ${req.user!.displayName}`)
  console.log(req.user!.displayName)
})

如果不想用断言,也可以用可选链操作符?.:req.user?.displayName,效果完全一致。

可选优化:给isLoggedIn中间件加上TypeScript类型

修改middleware.ts代码,补充类型定义避免后续其他类型报错:

import { Request, Response, NextFunction } from 'express';

const isLoggedIn = (req: Request, res: Response, next: NextFunction): void => {
  if (req.user) {
    next();
  } else {
    res.status(401).send('Not Logged In');
  }
};

export default isLoggedIn;

内容的提问来源于stack exchange,提问作者udhay r

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:24:03