【问题标题】:Typescript Declaration Merging fail about Express Request关于 Express 请求的 Typescript 声明合并失败
【发布时间】:2020-11-05 15:18:57
【问题描述】:

当我扩展快递请求时,我得到了这个错误。

error TS2339: Property 'test' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs>'.

这是我扩展请求的测试代码。

app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }),
  function(req: Request, res: Response) {
    req.test = 'aa'
    return console.log(req.test)
});

为了解决它,我已经搜索了很多,我做到了。

制作types/express/index.d.ts 文件。我在tsconfig.json 中添加 typeRoots,如下所示。

"typeRoots": ["./node_modules/@types", "./types"],

这是 types/express/index.d.ts 文件,我尝试了什么。

declare namespace Express {
    export interface Request {
        test: string
    }
}

// This is also fail
declare namespace Express {
    interface Request {
        test: string
    }
}

// This is also fail
declare global {
  namespace Express {
    interface Request {
        test: string
    }
  }
}

即使我的vscode 告诉我req.test 类型是字符串,服务器也会显示错误。

这是控制台上的完整错误

[nodemon] starting `ts-node src/app.ts`

/app/node_modules/ts-node/src/index.ts:434
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
src/app.ts(67,9): error TS2339: Property 'test' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs>'.
src/app.ts(68,28): error TS2339: Property 'test' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs>'.

    at createTSError (/app/node_modules/ts-node/src/index.ts:434:12)
    at reportTSError (/app/node_modules/ts-node/src/index.ts:438:19)
    at getOutput (/app/node_modules/ts-node/src/index.ts:578:36)
    at Object.compile (/app/node_modules/ts-node/src/index.ts:775:32)
    at Module.m._compile (/app/node_modules/ts-node/src/index.ts:858:43)
    at Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
    at Object.require.extensions.<computed> [as .ts] (/app/node_modules/ts-node/src/index.ts:861:12)
    at Module.load (internal/modules/cjs/loader.js:986:32)
    at Function.Module._load (internal/modules/cjs/loader.js:879:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)

这是我的 package.json,你可以看到我的 typescript 版本是 3.9.6

{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "start": "nodemon --exec ts-node src/app.ts",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "express-session": "^1.17.1",
    "jsonwebtoken": "^8.5.1",
    "nodemon": "^2.0.4",
    "passport": "^0.4.1",
    "passport-google-oauth20": "^2.0.0",
    "ts-node": "^8.10.2"
  },
  "devDependencies": {
    "@types/body-parser": "^1.19.0",
    "@types/cors": "^2.8.6",
    "@types/express": "^4.17.7",
    "@types/express-session": "^1.17.0",
    "@types/jsonwebtoken": "^8.5.0",
    "@types/node": "^14.0.18",
    "@types/passport": "^1.0.4",
    "@types/passport-google-oauth20": "^2.0.3",
    "typescript": "^3.9.6"
  }
}

这是我所有的 tsconfig.json

{
  "compilerOptions": {
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    "sourceMap": true,                     /* Generates corresponding '.map' file. */
    "outDir": "./dist",                        /* Redirect output structure to the directory. */
    "removeComments": true,                /* Do not emit comments to output. */
    "strict": true,                           /* Enable all strict type-checking options. */
    "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    "typeRoots": ["./node_modules/@types", "./types"],                       /* List of folders to include type definitions from. */
    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    "skipLibCheck": true,                     /* Skip type checking of declaration files. */
    "forceConsistentCasingInFileNames": true  /* Disallow inconsistently-cased references to the same file. */
  },
  "exclude": [
      "nod_modules",
      "**/*.spec.ts"
  ]
}

我从昨天开始花时间和压力。我该如何解决?

【问题讨论】:

  • 如果你尝试用 tsc 编译会发生什么? ./node_modules/.bin/tsc?
  • @torkel 当我在与 tsconfig.json 相同的路径中执行 .\node_modules\.bin\tsc.cmd 时。没有什么可显示的
  • 那么您的 TypeScript 配置似乎没有任何问题,而这是 ts-node 的问题。请参阅我的更长答案以获取解决方案。

标签: typescript type-extension


【解决方案1】:

这似乎是您如何配置 ts-node 的问题。为了简单起见并加快启动速度,我建议将-T/--transpile-only 添加到您的ts-node 参数中,这样您的start 脚本就变为nodemon --exec ts-node -T src/app.ts

此选项可防止ts-node 对您的代码运行类型检查。这有几个好处:

  1. 避免tsc(TypeScript 编译器)和ts-node 之间的配置冲突
  2. ts-node 启动更快
  3. 即使编译器出现故障,您也可以运行服务器,这在开发中非常有用。

请注意,您从不想要提交或合并无法正确编译的代码 tsc。您可以通过在 CI(持续集成)上检查这一点或作为预提交挂钩来做到这一点。如果您将"tsc": "tsc" 添加到package.json 中的scripts,您可以使用npm run tscyarn tsc 来编译您的代码。

您可以在此处阅读有关 ts-node CLI 标志的更多信息:https://www.npmjs.com/package/ts-node#cli-and-programmatic-options

【讨论】:

  • 感谢您的评论。最后没有错误。但是昨天当我检查 tsc 时,我只命令 tsc。当我今天检查 tsc /src/app.ts 时,我发现关于 node_modules/index.d.ts 错误文本是 This module is declared with using 'export =', and can only be used with a default import when using the 'esModuleInterop' flag 但我将 esModuleInterop 设置为 true。我该如何解决?
  • 似乎 tsc 正在编译您的 node_modules 文件夹。尝试将 skipLibCheck 添加到您的 tsconfig。但实际上,这应该是它自己的问题;)
猜你喜欢
  • 2021-07-08
  • 2020-11-15
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 2018-03-01
  • 1970-01-01
  • 2016-07-05
  • 1970-01-01
相关资源
最近更新 更多