将Node.js项目从纯ES6迁移到TypeScript

Ale*_*ler 7 node.js typescript typescript3.0

是否已开始将Node.js项目从普通ES6迁移到TypeScript.

我做了什么:

npm install -g typescript
npm install @types/node --save-dev
Run Code Online (Sandbox Code Playgroud)

设置tsconfig.json:

{
     "compilerOptions": {
         "emitDecoratorMetadata": true,
         "experimentalDecorators": true,
         "moduleResolution": "node",
         "module": "commonjs",
         "target": "es6",
         "sourceMap": true,
         "outDir": "dist",
         "allowJs": true,
         "forceConsistentCasingInFileNames": true
     },
     "exclude": [
         "node_modules",
         "dist",
         "docs"
     ]
}
Run Code Online (Sandbox Code Playgroud)

将所有文件扩展名更改.js.ts(除了node_modules):

find . -not \( -path node_modules -prune \) -iname "*.js" -exec bash -c 'mv "$1" "${1%.js}".ts' - '{}' \;
Run Code Online (Sandbox Code Playgroud)

tsc现在运行会导致大量错误,例如:

server.ts:13:7 - error TS2451: Cannot redeclare block-scoped variable 'async'.

13 const async = require('async');
     ~~~~~
Run Code Online (Sandbox Code Playgroud)

或者这些:

bootstrap/index.ts:8:7
8 const async = require('async');
        ~~~~~
'async' was also declared here.
Run Code Online (Sandbox Code Playgroud)

更新:

同样的情况对retrynpm包:

const retry = require('retry');
Run Code Online (Sandbox Code Playgroud)

require语句更改为ES6 import语句大多修复了这些问题但是必须同时迁移几千个文件是不可行的,所以我需要一种方法来坚持require一段时间.这可能吗?

Sty*_*tyx 7

这是可能的,但您仍然需要编辑这些文件.

这些方法中的任何一种都足够了.

  1. 替换const ... = require()import ... = require():

    import async = require('async');
    ...
    
    Run Code Online (Sandbox Code Playgroud)
  2. 添加export {}到文件顶部:

    export {};
    const async = require('async');
    ...
    
    Run Code Online (Sandbox Code Playgroud)

初始问题的原因是在TS中,不同的文件不是模块,除非它们显式声明为模块,因此它们在同一全局范围内编译/执行,这就是为什么tsc报告您async变量无法重新声明的原因.

来自文档:

在TypeScript中,就像在ECMAScript 2015中一样,任何包含顶级文件import或被export视为模块的文件.相反,没有任何顶级importexport声明的文件被视为脚本,其内容在全局范围内可用(因此也可用于模块).


Est*_*ask 4

这和这个是同样的问题。

为了被视为 ES 模块,文件应包含importorexport语句,否则变量将被视为由 TypeScript 编译器在全局范围内声明(即使在运行时并非如此)。

解决方案与链接问题中的相同,添加 dummy export {}。这可以通过正则表达式替换批量完成,但如果 CommonJS 、module.exports = ...导出已在使用中,它们之间可能会发生冲突。

使用 CommonJSrequire()导入会产生无类型代码。所有主要的库都已经有相应的@types/...或内置的类型。现有的 NPM 包可以与代码库中的正则表达式匹配,以便@types/...批量安装相关包,导入之类的const async = require('async')可以批量替换为import async from 'async'. 这需要设置选项esModuleInteropallowSyntheticDefaultImports