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

通过d.ts扩展Express.User后出现TypeScript编译错误

问题描述

我在Express + Passport的TypeScript项目中,尝试通过.d.ts文件扩展Express.User类型,让req.user能携带自定义IUser的属性。但编译时始终报错Property '_id' does not exist on type 'User',尽管IDE能正常识别类型并自动补全,运行时也能打印出包含_id的用户数据。

相关代码

类型扩展文件 src/interfaces/expressExtend.d.ts

import IUser from "./src/interfaces/userInterface";

declare global {
  namespace Express {
    export interface User extends IUser {}
  }
}

路由校验代码 index.ts

import { Request, Response } from 'express';

app.get('/auth-check', async (req: Request, res: Response) => {
  console.log('SESSION => ', req.session);
  console.log('USER => ', req.user);
  const userId = req.user?._id ?? undefined; // 编译报错:Property '_id' does not exist on type 'User'
  if (userId) {
    res.sendStatus(200);
  } else {
    res.sendStatus(401);
  }
});

tsconfig.json 配置

{
  "compilerOptions": {
    "module": "NodeNext",
    "target": "ES2022",
    "strict": true,
    "noUnusedLocals": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": true,
    "esModuleInterop": true,
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "rootDir": "src",
    "typeRoots": [ "node_modules/@types", "src/interfaces"],
  },
  "include": ["**/*.ts", "**/*.tsx", "src/**/*", "src/interfaces/expressExtend.d.ts"],
  "exclude": ["node_modules", "dist"]
}

已尝试的无效操作

  • 在typeRoots中指定.d.ts文件路径而非仅文件夹
  • 在include中明确指定.d.ts文件路径
  • 检查Passport是否覆盖自定义类型(未发现覆盖)
  • 将.d.ts文件移至项目根目录并更新引用
  • 修改.d.ts文件:移除export interface User中的export,添加空的export {}
  • 在index.ts中直接导入.d.ts文件

解决方案

问题核心是NodeNext模块系统下的全局声明处理逻辑,以及类型文件的模块属性配置错误,按以下步骤修复:

1. 修正expressExtend.d.ts的模块与路径

由于文件中使用了import,会被识别为ES模块,此时必须添加export {}标记模块上下文,同时修正导入路径(原路径存在层级错误):

// src/interfaces/expressExtend.d.ts
import IUser from "./userInterface"; // 从当前文件夹导入,而非上级目录

declare global {
  namespace Express {
    interface User extends IUser {} // 移除export,Express.User是全局命名空间接口,无需重新导出
  }
}

export {}; // 标记为模块,确保全局声明生效

2. 调整tsconfig.json配置

  • 移除typeRoots中的src/interfaces:typeRoots用于指定第三方类型包目录,自定义类型通过include即可覆盖,无需放入其中
  • 简化include配置,确保覆盖所有src下的文件:
{
  "compilerOptions": {
    "module": "NodeNext",
    "target": "ES2022",
    "strict": true,
    "noUnusedLocals": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": true,
    "esModuleInterop": true,
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "rootDir": "src",
    "typeRoots": [ "node_modules/@types" ]
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

3. 清理缓存重新编译

执行以下命令清理TypeScript缓存并重新编译:

rm -rf node_modules/.cache
npx tsc --build --clean
npx tsc

内容的提问来源于stack exchange,提问作者Dan-DH

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:04:56