开始将Node.js项目从普通ES6迁移到TypeScript。
我所做的:
npm install -g typescript
npm install @types/node --save-dev设置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"
]
}将所有文件扩展名从.js更改为.ts (node_modules除外):
find . -not \( -path node_modules -prune \) -iname "*.js" -exec bash -c 'mv "$1" "${1%.js}".ts' - '{}' \;运行tsc现在会导致大量的错误,如下所示:
server.ts:13:7 - error TS2451: Cannot redeclare block-scoped variable 'async'.
13 const async = require('async');
~~~~~或者这些:
bootstrap/index.ts:8:7
8 const async = require('async');
~~~~~
'async' was also declared here.更新:
retry和其他npm包也是如此:
const retry = require('retry');将require语句更改为ES6 import语句主要解决了这些问题,但是必须一次迁移数千个文件是不可能的,所以我需要一种方法来坚持使用require。这个是可能的吗?
发布于 2019-01-13 13:31:02
这是与这一个相同的问题。
为了被视为ES模块,文件应该包含import或export语句,否则变量将被TypeScript编译器视为在全局范围内声明(即使在运行时不是这样)。
该解决方案与链接问题中的解决方案相同,即添加虚拟export {}。这可以通过regex替换成批完成,但是如果CommonJS、module.exports = ...导出已经在使用,它们之间可能会发生冲突。
使用CommonJS require()导入会导致非类型化代码。所有主要的库都已经按照@types/...或内置类型进行了分类。现有的NPM包可以与代码库中的regex匹配,以便批量安装相关的@types/...包,像const async = require('async')这样的导入可以用import async from 'async'批量替换。这需要设置esModuleInterop和allowSyntheticDefaultImports选项。
发布于 2019-01-12 23:09:03
这是可能的,但你仍然需要编辑那些文件。
这两种方法都足够了。
const ... = require()替换为import ... = require():
导入异步=要求(‘异步’);.export {}添加到文件的顶部:
导出{};const异步=要求(‘异步’);.初始问题的原因是,在TS中,不同的文件不是模块,除非它们显式声明为模块,因此它们在相同的全局范围内编译/执行,这就是为什么tsc报告不能重新声明async变量的原因。
来自文档
在TypeScript中,就像在ECMAScript 2015中一样,任何包含顶级
import或export的文件都被视为模块。相反,没有任何顶级的importexport或export声明的文件被视为一个脚本,其内容在全局范围内可用(因此也适用于模块)。
发布于 2019-01-13 14:34:17
异步是一个受保护的关键字。当你使用异步/等待时,你可以跳过‘异步’包。如果您使用ES6+模块( ECMAScript made,ESM)正确地创建了,那么您还可以重命名所有文件-- *.mjs,例如index.mjs。如果您有文件名index.js,则通常假定它不是ESM。您必须向所有的ES6代码中添加类型/接口,因此根据您的情况,可能不可能一次性完成所有操作,这就是为什么我给出了ES2015+ ESM表示法中的示例。
对于TypeScript,您应该能够使用ESM,因为我想您需要更多最新的符号。为了在顶层使用异步,存在异步函数。 index.mjs示例代码,包括从ES5/CommonJS *.js导入ES2015+和ESM导入/导出,最后是动态导入:
import { createRequireFromPath } from 'module'; // ESM import
import { fileURLToPath } from 'url';
const require = createRequireFromPath(fileURLToPath(import.meta.url));
// const untypedAsync = require('async');
class Index {
constructor() {
this._server = null;
this.host = `localhost`;
this.port = 8080;
}
set server(value) { this._server = value; }
get server() { return this._server; }
async start() {
const http = await import(`http`); // dynamic import
this.server = http.createServer(this.handleRequest);
this.server.on(`error`, (err) => {
console.error(`start error:`, err);
});
this.server.on(`clientError`, (err, socket) => {
console.error(`start clientError:`, err);
if (socket.writable) {
return socket.end(`HTTP/1.1 400 Bad Request\r\n\r\n`);
}
socket.destroy();
});
this.server.on(`connection`, (socket) => {
const arrival = new Date().toJSON();
const ip = socket.remoteAddress;
const port = socket.localPort;
console.log(`Request from IP-Address ${ip} and source port ${port} at ${arrival}`);
});
this.server.listen(this.port, this.host, () => {
console.log(`http server listening at ${this.host}:${this.port}`);
});
}
handleRequest(req, res) {
console.log(`url:`, req.url);
res.setHeader(`Content-Type`, `application/json`);
res.writeHead(200);
res.end(JSON.stringify({ url: req.url }));
}
}
export default Index; // ESM export
export const randomName = new Index(); // Usage: import { randomName } from './index.mjs';
async function main() {
const index = new Index();
const cjs = require(`./otherfile.js`); // ES5/CommonJS import
console.log(`otherfile:`, cjs);
// 'async' can be used by using: cjs.untypedAsync
await index.start();
}
main();
// in otherfile.js
const untypedAsync = require('async');
const test = {
url: "url test",
title: "title test",
};
module.exports = { test, untypedAsync }; // ES5/CommonJS export.然而,使用.mjs与类型记录目前存在一些问题。请查看仍未解决的相关类型记录问题:.mjs输入文件和.mjs输出文件。您至少应该将您的.ts转到.mjs以解决您的问题。脚本看起来可能类似于(es6到ts源):
// in package.json
"files": [ "dist" ],
"main": "dist/index",
"types": "dist/index.d.ts",
"scripts": {
"mjs": "tsc -d && mv dist/index.js dist/index.mjs",
"cjs": "tsc -m commonjs",
"start": "node --no-warnings --experimental-modules ./dist/index.mjs"
"build": "npm run mjs && npm run cjs"
},
"devDependencies": {
"typescript": "^3.2.2"
}
// in tsconfig.json
"compilerOptions": {
"module": "es2015",
"target": "ES2017",
"rootDir": "src",
"outDir": "dist",
"sourceMap": false,
"strict": true
}https://stackoverflow.com/questions/54137397
复制相似问题