使用不同的类方法,具体取决于使用的目标编译器选项



如何告诉 TypeScript 使用不同的编写方法(在同一类上),具体取决于tsconfig.json文件中使用的target选项?

我目前正在将我的一个脚本重写到 TypeScript 中以"管理"一个源,因为目前我正在使用彼此相邻的 ES5 和 ES6 文件。由于 TypeScript 只支持更改tsconfig.json文件中的输出目标,因此我只需要一个版本即可更新和维护。

问题是我在 ES6 版本中使用的是生成器,理论上不应该是这个问题,因为 TypeScript 将伪生成器"添加"到我的 ES5 文件的顶部。但是:我目前正在 ES5 文件上使用的伪生成器代码"更干净",代码更少。

问题

是否可以覆盖相应的"生成器"方法或使用任何特殊的注释注释(例如//@ts-target)来告诉编译器应该使用哪个代码(函数体),具体取决于配置文件中使用的target?(即使我在官方文档中找不到这样的解决方案)。

我想,可以添加到 TypeScript 编译器过程中的附加函数或脚本也会有所帮助,因为我正在使用一个小节点.js脚本编译它们(它编译两个 ES 文件而不直接更改tsconfig.json文件。

或者是否有任何类型的扩展名,将同一类的不同方法移动到不同的文件中?这样我就可以"提取"相应的"生成器"方法,但这会导致另一个问题:如何根据目标链接它们,因为我正在使用主脚本文件上的/// <reference />链接来将所有方法组合在一起。

还有其他想法吗?

class Option {
///@ts-target ES5
__walkerVariable1:any undefined
__walkerVariable2:any undefined
__walkerVariable3:any undefined
walker() {
/* Some Pseudo-Walker Code for ES5 */
}
///@ts-target ES6
*walker() {
/* Real Walker Code for ES6 */
}
}

目前,伪生成器代码已添加到我的脚本的 ES5 版本中。我想通过在我自己的伪生成器中使用不同的方法/函数体来防止这种情况。因此,我需要告诉 TypeScript,他应该"忽略"ES6 中的伪生成器/ES5 中的真实生成器,并根据使用的target选项渲染其中一个。

这有点棘手,但由于这个 GitHub 问题,我找到了解决方案。

如上所述,我使用自己的 node.js 脚本将 TypeScript 文件编译成两个不同的 JavaScript 版本(ES5 和 ES6)。因此,我将 TypeScript API 与ts.createProgram方法一起使用。此方法允许添加主机对象作为第三个参数,该参数接管一些编译器进程,其中一个是文件加载器,称为getSourceFile

剩下的就相对容易了:搜索自定义注释注释(在我的例子中分别为\@ts-target:ES5\@ts-target:ES6)并使用 RegExp 过滤它们。也许不是最好的解决方案,但它有效!

function compileTS(){
let config = readConfig("ts/tsconfig.json");
let host = ts.createCompilerHost(config.options);
let sourceFile = host.getSourceFile;
// ES5 JavaScript
(function(config){
host.getSourceFile = function(filename) {
if(filename === "ts/options.ts"){
let file = fs.readFileSync("./ts/options.ts").toString();
file = file.replace(/[ ]+///@ts-target:ES6s+([sS]*)///@ts-target:ES6/gm, "");
return ts.createSourceFile(filename, file, ts.ScriptTarget.ES5, true);
}
return sourceFile.call(host, filename);
}
let program = ts.createProgram(config.fileNames, config.options, host);
let emitResult = program.emit();
report(ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics));
if(emitResult.emitSkipped){
process.exit(1);
}
}(config));
// ES6 JavaScript
config.options.target = 2;
config.options.outFile = "../dist/js/tail.select-es6.js";
(function(config){
host.getSourceFile = function(filename) {
if(filename === "ts/options.ts"){
let file = fs.readFileSync("./ts/options.ts").toString();
file = file.replace(/[ ]+///@ts-target:ES5s+([sS]*)///@ts-target:ES5/gm, "");
return ts.createSourceFile(filename, file, ts.ScriptTarget.ES2015, true);
}
return sourceFile.call(host, filename);
}
let program = ts.createProgram(config.fileNames, config.options, host);
let emitResult = program.emit();
report(ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics));
if(emitResult.emitSkipped){
process.exit(1);
}
}(config));
}

最新更新