运行 带有 es6 模块的 TypeScript Mocha

Running TypeScript Mocha with module es6

我想为我的 Rails 应用程序的 TypeScript 应用程序设置一些 mocha 测试。我添加了一个愚蠢的测试来开始。但我不断收到此错误:

/home/bernhard/Programs/ruby/cube_trainer/jstests/utils/optional.spec.ts:1
import { some, none, mapOptional, forceValue, hasValue, checkNone } from '../../app/javascript/cube_trainer/app/utils/optional';
^^^^^^

SyntaxError: Cannot use import statement outside a module
...stacktrace...
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

我通过反复试验发现 tsconfig.json 中的 "module": "es6" 行似乎是导致此问题的原因。如果我将其更改为 "module": "commonjs",我的测试将运行并通过。但是,如果我这样做,我的 rails 应用程序将停止工作。

如果我达到以下任一条件,我认为这个问题已经解决: * 让我的 Rails 应用程序使用 "module": "commonjs" 选项。 * 让我的测试与 "module": "es6" 一起工作 * 我设法为 mocha 使用不同的 tsconfig(但如果我可以包含现有的 tsconfig 并只更改一个选项而不是复制整个文件,我只会考虑这个选项)

顺便说一句,我对所有这些配置选项都没有深入的了解,我只是将粘贴的东西复制在一起,直到它起作用为止。因此,如果我的配置中有任何愚蠢的地方,请随时指出。我有意做的唯一一件事是,只要我能在不破坏我无法控制的事情的情况下做到这一点,我就让 TypeScript 尽可能严格。

重要参考文件

完整的回购协议在这里:https://github.com/Lykos/cube_trainer 自述文件包含安装说明(如果您已经安装了 postgresql、yarn 和 ruby,应该很简单)

tsconfig.json

{
  "compilerOptions": {
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
      "lib": ["dom", "es2017"],
    "module": "es6",
    "moduleResolution": "node",
    "baseUrl": ".",
    "paths": {
        "*": ["node_modules/*", "app/javascript/*"]
    },
    "sourceMap": true,
    "target": "es6",
    "removeComments": false,
    "strict": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": true,
    "noUnusedLocals": true,
    "noImplicitThis": true,
    "noImplicitReturns": true
  },
  "exclude": [
    "**/*.spec.ts",
    "node_modules",
    "vendor",
    "public"
  ],
  "compileOnSave": false
}

请注意,我的 tsconfig 源自 Rails 提供的配置。看这里:

https://github.com/rails/webpacker/blob/master/lib/install/examples/typescript/tsconfig.json

我将 "lib": ["es6", "dom"], 更改为 "lib": ["dom", "es2017"], 以解决问题,我将目标更改为 es6 并添加了更多选项以使 TypeScript 更严格。

我不知道这些选项在一般情况下是否有意义,但我很难尝试让我的应用程序与 Rails 和 TS 一起工作,但没有这些选项。

package.json

{
  "name": "cube_trainer",
  "private": true,
  "dependencies": {
    "@angular/animations": "^9.0.0",
    "@angular/cdk": "^9.2.0",
    "@angular/common": "^9.1.0",
    "@angular/compiler": "^9.1.0",
    "@angular/core": "^9.1.0",
    "@angular/forms": "^9.1.0",
    "@angular/material": "^9.2.0",
    "@angular/platform-browser": "^9.1.0",
    "@angular/platform-browser-dynamic": "^9.1.0",
    "@angular/router": "^9.1.0",
    "@rails/actioncable": "^6.0.0",
    "@rails/activestorage": "^6.0.0",
    "@rails/ujs": "^6.0.0",
    "@rails/webpacker": "5.0.1",
    "@rxweb/reactive-form-validators": "^1.9.9-beta4",
    "angular-new-router": "angular/router",
    "core-js": "^3.6.4",
    "es6-shim": "^0.35.0",
    "html-loader": "^1.0.0",
    "http-methods-enum": "^0.1.1",
    "jquery": "^3.4.1",
    "material-design-icons": "^3.0.1",
    "rails-ujs": "^5.2.4-2",
    "reflect-metadata": "0.1.2",
    "rxjs": "^6.5.3",
    "snake-case-typescript": "^0.0.2",
    "ts-loader": "^6.2.2",
    "tslib": "^1.10.0",
    "turbolinks": "^5.2.0",
    "typescript": "^3.8.3",
    "webpack": "^4.42.1",
    "zone.js": "~0.10.2"
  },
  "author": "Bernhard F. Brodowsky",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/Lykos/cube_trainer.git"
  },
  "scripts": {
    "test": "mocha -r ts-node/register jstests/**/*.spec.ts"
  },
  "version": "0.1.0",
  "devDependencies": {
    "@types/chai": "^4.2.11",
    "@types/mocha": "^7.0.2",
    "@types/node": "^12.12.31",
    "chai": "^4.2.0",
    "mocha": "^7.1.1",
    "ts-node": "^8.9.0",
    "webpack-dev-server": "^3.10.3"
  }
}

我找到了解决办法。基本上我需要在 tsconfig.json 中用 "module": "commonjs" 替换 "module": "es6"。鉴于这导致了其他问题,我需要一个聪明的解决方案。一种可能性是使用多个 TS 配置。最后,我决定在运行它的脚本中通过环境变量覆盖它。像这样:

  "scripts": {
    "test": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' mocha -r ts-node/register jstests/**/*.spec.ts"
  },