【问题标题】:Does TypeScript provide an explicit Public API for NodeJS Module Access?TypeScript 是否为 NodeJS 模块访问提供显式公共 API?
【发布时间】:2012-09-24 21:38:04
【问题描述】:

从我想做的节点应用程序中:

var typeScript = require('typescript'); 

typeScript.compile('...')

我希望将编译器实现到构建系统中,但无法访问公共 API(typescript.compile 等),这是不可能的。

这是我想做的更完整的示例,尽管下面是针对 LiveScript,而不是 TypeScript,在为 Brunch.io 构建系统编写的插件中使用:

LiveScript = require 'LiveScript'
sysPath = require 'path'

module.exports = class LiveScriptCompiler
  brunchPlugin: yes
  type: 'javascript'
  extension: 'ls'

  constructor: (@config) ->
    null

  compile: (data, path, callback) ->
    try
      result = LiveScript.compile data, bare: yes
    catch err
      error = err
    finally
      callback error, result

  include: [
    (sysPath.join __dirname, '..', 'vendor', 'prelude-browser-0.6.0.js')
  ]

想知道是否有人找到了解决方法?

更新

我最终针对上面和其他地方列出的各种问题实施了自己的解决方案。请参阅https://github.com/damassi/TypeScript-Watcher 了解更多信息和用法。

【问题讨论】:

    标签: javascript node.js typescript tsc


    【解决方案1】:

    你可以试试https://github.com/sinclairzx81/typescript.api。这个项目做了 require() 扩展的东西,但也有一些手动编译 ts 源的功能。应该可以用它创建一个自动构建系统。

    请注意它是基于 typescript 0.9 编译器构建的,因此考虑到语言的各种更新,您可能成功编译 0.8.3 源代码,也可能不成功。

    【讨论】:

      【解决方案2】:

      better-require 可以帮助您实现这一点,如果您只想执行/访问 typescript 文件。

      它允许您 require() typescript 文件 - 无需预编译 - 以及一堆其他文件格式(coffeescript、clojurescript、yaml、xml 等)

      require('better-require')();
      var myModule = require('./mymodule.ts');
      

      披露:我写了更好的要求。

      【讨论】:

      • 很棒的实用工具 -- 我现在要试一试,尝试将其修补到 Brunch.io 汇编程序中。
      • 谢谢!随意拉请求;)这很简单。
      【解决方案3】:

      检查 niutech 的 this github project,它可以在 在浏览器中即时将 TypeScript 代码转换为 JS 代码,但我想它可以很容易地修改为在 node.js 中工作。

      【讨论】:

      • 感谢您提及我的项目!
      【解决方案4】:

      这个有点hacky,但它会工作。

      我昨天也想过这个问题,我正在检查他们的代码。如果你从他们的源代码中检查 bin/typscript.js(这是一个非常非常大的文件,有将近 21k 行代码),你会看到它创建了 TypeScript.TypeScriptCompiler,然后你会发现这确实暴露了一种编译方式.

      var compiler = new TypeScript.TypeScriptCompiler(outfile, errorfile, 
          new TypeScript.NullLogger(), settings);
      

      现在,您需要一种简单的方法来公开它。为此,您将不得不修改他们的代码,这就是为什么这是 hacky。为此,您可以通过添加以下内容来修改 typescript.js:

      module.exports = exports = TypeScript;
      

      就在文件的末尾。

      然后,您可以在模块的根目录中创建一个 index.js 文件(注意:将模块安装在所有这些的本地范围内:“npm install typescript”),它会公开对象。

      exports.TypeScript = require("bin/typescript");
      

      准备好了!现在你可以调用它并使用它编译你的代码。您可以在 tsc.js 文件中查看如何使用 API 进行编译。

      我为前面的可怕代码提前道歉:

      var fs = require("fs");
      var TypeScript = require("typescript");
      var path = "test.ts";
      var pathout = "test.js";
      var content = fs.readFileSync(path, "utf-8");
      var fd = fs.openSync(pathout, 'w'); 
      var outFile = { 
          Write: function (str) { 
              fs.writeSync(fd, str); 
          }, 
          WriteLine: function (str) {
          console.log(fd, str); 
              fs.writeSync(fd, str + '\r\n'); 
          }, 
          Close: function () { 
              fs.closeSync(fd); 
              fd = null; 
          } 
      };
      var createFile = function (path) { 
          function mkdirRecursiveSync(path) { 
              var stats = fs.statSync(path); 
              if(stats.isFile()) { 
                  throw "\"" + path + "\" exists but isn't a directory."; 
              } else { 
                  if(stats.isDirectory()) { 
                      return; 
                  } else { 
                      mkdirRecursiveSync(_path.dirname(path)); 
                      fs.mkdirSync(path, 509); 
                  } 
              } 
          } 
          mkdirRecursiveSync(_path.dirname(path));
          console.log(path) 
          var fd = fs.openSync(path, 'w'); 
          return { 
              Write: function (str) { 
                  fs.writeSync(fd, str); 
              }, 
              WriteLine: function (str) { 
                  fs.writeSync(fd, str + '\r\n'); 
              }, 
              Close: function () { 
                  fs.closeSync(fd); 
                  fd = null; 
              } 
          }; 
      };
      var stderr = { 
          Write: function (str) { 
              process.stderr.write(str); 
          }, 
          WriteLine: function (str) { 
              process.stderr.write(str + '\n'); 
          }, 
          Close: function () { 
          } 
      }
      var compiler = new TypeScript.TypeScriptCompiler(outFile, outFile);
      compiler.setErrorOutput(stderr);
      compiler.addUnit(content, path);
      compiler.typeCheck();
      compiler.emit(false, createFile);
      outFile.Close();
      

      出于某种原因,编写代码的人是 C# 的忠实粉丝,并继续使用称为 WriteLine、Close 和 Write 的方法,这些方法实际上只是包装器。您可能会因为必须添加此函数而产生开销,但您必须修改模块中的大量代码,这是不值得的。我认为最好有一个类来扩展(或者如果你还在 JS 上,继承原型)并让它为你做这件事,让它 DRY。

      非常棒的一点是,如果你想翻译 500 个 TypeScript 文件并将它们全部放入一个 .js 文件中,你可以调用 compiler.addUnit(anothercontent, anotherpath); 500 次,然后看到它全部进入一个文件:)

      专注于更好的事情:如果你检查 tsc.js 代码,你会发现一个批处理编译器类。如果您希望将其用于构建过程,则最好使用类似它的更健壮的东西。它提供观看文件等等。

      浏览了代码后,我想我只是向开发团队提交一张票,并要求他们提供更清晰的 API ¬¬

      注意:这里的所有文件读取都是以同步方式完成的。就性能而言,这很糟糕,非常糟糕。我不确切知道您打算做什么,但是如果可能的话,我不能建议您找到一种使此异步的方法。

      【讨论】:

      • 优秀的答案。期待你的榜样。
      • 完成!您可以使用它,只需更改文件名(它是 test.js 和 test.ts)并给它其他文件名,它就会工作。现在的方式是,错误输出将被释放到 process.stderr,但你可以用它做任何你想做的事情。您还可以添加一个处理函数作为compiler.setErrorCallback,这样您就可以报告构建错误!
      【解决方案5】:

      目前仅通过 require 并调用 compile 是无法实现编译的。如果您可以查看harness.ts,则有一个编译器模块提供了一种相当简单的方法,但我建议您从外部调用 tsc。

      ///<reference path='node.d.ts'/>
      import exec = module('child_process');
      
      var child = exec.exec('tsc foo.ts',
        function (error, stdout, stderr) {
          if (error !== null) {
            console.log('exec error: ' + error);
          }
      });
      

      我相信这可以完成这项工作。

      【讨论】:

      • 你可能想删除这个答案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多