如何监视和编译所有 TypeScript 源代码?

我试图转换一个宠物项目到 TypeScript,似乎不能使用 tsc实用程序来观察和编译我的文件。这个帮助说明我应该使用 -w开关,但是它看起来不能递归地观察和编译某个目录中的所有 *.ts文件。这似乎是 tsc应该能够处理的问题。我有什么选择?

187214 次浏览

从技术上讲,你有几个选择:

如果您正在使用一个 IDE,如 Sublime Text 和集成的 MSN 插件的 Typecript: http://blogs.msdn.com/b/interoperability/archive/2012/10/01/sublime-text-vi-emacs-typescript-enabled.aspx,您可以创建一个构建系统,自动编译 .ts源代码到 .js。下面是如何做到这一点的解释: 如何为 TypeScript 配置升华生成系统

您甚至可以在文件保存时定义将源代码编译到目标 .js文件。在 github: https://github.com/alexnj/SublimeOnSaveBuild上有一个令人赞叹的包,它可以实现这一点,只是您需要在 SublimeOnSaveBuild.sublime-settings文件中包含 ts扩展。

另一种可能性是在命令行中编译每个文件。您甚至可以一次编译多个文件,方法是使用如下的空格将它们分隔开: tsc foo.ts bar.ts。检查这个线程: 如何将多个源文件传递给 TypeScript 编译器?,但我认为第一个选项更方便。

Tsc 编译器将只监视在命令行上传递的那些文件。它将使用 /// <sourcefile>引用包含 没有监视文件。如果使用 bash,可以使用 find 递归地查找所有 *.ts文件并编译它们:

find . -name "*.ts" | xargs tsc -w

今天我设计这个 Ant MacroDef 是为了解决和你们一样的问题:

    <!--
Recursively read a source directory for TypeScript files, generate a compile list in the
format needed by the TypeScript compiler adding every parameters it take.
-->
<macrodef name="TypeScriptCompileDir">


<!-- required attribute -->
<attribute name="src" />


<!-- optional attributes -->
<attribute name="out" default="" />
<attribute name="module" default="" />
<attribute name="comments" default="" />
<attribute name="declarations" default="" />
<attribute name="nolib" default="" />
<attribute name="target" default="" />


<sequential>


<!-- local properties -->
<local name="out.arg"/>
<local name="module.arg"/>
<local name="comments.arg"/>
<local name="declarations.arg"/>
<local name="nolib.arg"/>
<local name="target.arg"/>
<local name="typescript.file.list"/>
<local name="tsc.compile.file"/>


<property name="tsc.compile.file" value="@{src}compile.list" />


<!-- Optional arguments are not written to compile file when attributes not set -->
<condition property="out.arg" value="" else='--out "@{out}"'>
<equals arg1="@{out}" arg2="" />
</condition>


<condition property="module.arg" value="" else="--module @{module}">
<equals arg1="@{module}" arg2="" />
</condition>


<condition property="comments.arg" value="" else="--comments">
<equals arg1="@{comments}" arg2="" />
</condition>


<condition property="declarations.arg" value="" else="--declarations">
<equals arg1="@{declarations}" arg2="" />
</condition>


<condition property="nolib.arg" value="" else="--nolib">
<equals arg1="@{nolib}" arg2="" />
</condition>


<!-- Could have been defaulted to ES3 but let the compiler uses its own default is quite better -->
<condition property="target.arg" value="" else="--target @{target}">
<equals arg1="@{target}" arg2="" />
</condition>


<!-- Recursively read TypeScript source directory and generate a compile list -->
<pathconvert property="typescript.file.list" dirsep="\" pathsep="${line.separator}">


<fileset dir="@{src}">
<include name="**/*.ts" />
</fileset>


<!-- In case regexp doesn't work on your computer, comment <mapper /> and uncomment <regexpmapper /> -->
<mapper type="regexp" from="^(.*)$" to='"\1"' />
<!--regexpmapper from="^(.*)$" to='"\1"' /-->


</pathconvert>




<!-- Write to the file -->
<echo message="Writing tsc command line arguments to : ${tsc.compile.file}" />
<echo file="${tsc.compile.file}" message="${typescript.file.list}${line.separator}${out.arg}${line.separator}${module.arg}${line.separator}${comments.arg}${line.separator}${declarations.arg}${line.separator}${nolib.arg}${line.separator}${target.arg}" append="false" />


<!-- Compile using the generated compile file -->
<echo message="Calling ${typescript.compiler.path} with ${tsc.compile.file}" />
<exec dir="@{src}" executable="${typescript.compiler.path}">
<arg value="@${tsc.compile.file}"/>
</exec>


<!-- Finally delete the compile file -->
<echo message="${tsc.compile.file} deleted" />
<delete file="${tsc.compile.file}" />


</sequential>


</macrodef>

在构建文件中使用:

    <!-- Compile a single JavaScript file in the bin dir for release -->
<TypeScriptCompileDir
src="${src-js.dir}"
out="${release-file-path}"
module="amd"
/>

它用在我当时正在使用 Webstorm 进行的 用于 TypeScript 的 PureMVC项目中。

Tsc 0.9.1.1似乎没有 看好了特性。

You could use a PowerShell script like the one:

#watch a directory, for changes to TypeScript files.
#
#when a file changes, then re-compile it.
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "V:\src\MyProject"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$changed = Register-ObjectEvent $watcher "Changed" -Action {
if ($($eventArgs.FullPath).EndsWith(".ts"))
{
$command = '"c:\Program Files (x86)\Microsoft SDKs\TypeScript\tsc.exe" "$($eventArgs.FullPath)"'
write-host '>>> Recompiling file ' $($eventArgs.FullPath)
iex "& $command"
}
}
write-host 'changed.Id:' $changed.Id
#to stop the watcher, then close the PowerShell window, OR run this command:
# Unregister-Event < change Id >

参考: 自动监视和编译 TypeScript 文件

Look into using grunt to automate this, there are numerous tutorials around, but here's a quick start.

文件夹结构如下:

blah/
blah/one.ts
blah/two.ts
blah/example/
blah/example/example.ts
blah/example/package.json
blah/example/Gruntfile.js
blah/example/index.html

你可以很容易地从示例文件夹中观看和处理打字稿:

npm install
grunt

With package.json:

{
"name": "PROJECT",
"version": "0.0.1",
"author": "",
"description": "",
"homepage": "",
"private": true,
"devDependencies": {
"typescript": "~0.9.5",
"connect": "~2.12.0",
"grunt-ts": "~1.6.4",
"grunt-contrib-watch": "~0.5.3",
"grunt-contrib-connect": "~0.6.0",
"grunt-open": "~0.2.3"
}
}

还有一个粗重的文件:

module.exports = function (grunt) {


// Import dependencies
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-open');
grunt.loadNpmTasks('grunt-ts');


grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
connect: {
server: {  // <--- Run a local server on :8089
options: {
port: 8089,
base: './'
}
}
},
ts: {
lib: { // <-- compile all the files in ../ to PROJECT.js
src: ['../*.ts'],
out: 'PROJECT.js',
options: {
target: 'es3',
sourceMaps: false,
declaration: true,
removeComments: false
}
},
example: {  // <--- compile all the files in . to example.js
src: ['*.ts'],
out: 'example.js',
options: {
target: 'es3',
sourceMaps: false,
declaration: false,
removeComments: false
}
}
},
watch: {
lib: { // <-- Watch for changes on the library and rebuild both
files: '../*.ts',
tasks: ['ts:lib', 'ts:example']
},
example: { // <--- Watch for change on example and rebuild
files: ['*.ts', '!*.d.ts'],
tasks: ['ts:example']
}
},
open: { // <--- Launch index.html in browser when you run grunt
dev: {
path: 'http://localhost:8089/index.html'
}
}
});


// Register the default tasks to run when you run grunt
grunt.registerTask('default', ['ts', 'connect', 'open', 'watch']);
}

在项目根目录中创建一个名为 tsconfig.json的文件,并在其中包含以下代码行:

{
"compilerOptions": {
"emitDecoratorMetadata": true,
"module": "commonjs",
"target": "ES5",
"outDir": "ts-built",
"rootDir": "src"
}
}

请注意: outDir应该是接收已编译 JS 文件的目录的路径,而 rootDir应该是包含源代码的目录的路径(。文件。

Open a terminal and run tsc -w, it'll compile any .ts file in src directory into .js and store them in ts-built directory.

TypeScript 1.5 beta 引入了对称为 tsconfig.json的配置文件的支持。在该文件中,您可以配置编译器、定义代码格式化规则,更重要的是,您可以为其提供有关项目中的 TS 文件的信息。

正确配置之后,您可以简单地运行 tsc命令并让它编译项目中的所有 TypeScript 代码。

如果您想让它监视文件的更改,那么您可以简单地将 --watch添加到 tsc命令中。

Here's an example tsconfig.json file

{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false
},
"include": [
"**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]}

在上面的例子中,我在我的项目中包含了所有的 .ts文件(递归地)。注意,还可以使用带有数组的 "exclude"属性排除文件。

有关更多信息,请参考文档: http://www.typescriptlang.org/docs/handbook/tsconfig-json.html

你可以像这样看所有的文件

tsc *.ts --watch

编辑: 注意,这是在您的打字脚本源代码中有多个 tsconfig.json 文件的情况下。对于我的项目,我们将每个 tsconfig.json 文件编译成一个名称不同的。Js 文件。这使得查看每个打印文件非常容易。

我编写了一个超棒的 bash 脚本,它可以找到所有 tsconfig.json 文件并在后台运行它们,然后如果您使用 CTRL + C 终端,它将关闭所有正在运行的输入脚本 watch 命令。

这是在 MacOS 上测试的,但是应该可以在支持 BASH 3.2.57的任何地方工作。未来的版本可能已经改变了一些东西,所以要小心!

#!/bin/bash
# run "chmod +x typescript-search-and-compile.sh" in the directory of this file to ENABLE execution of this script
# then in terminal run "path/to/this/file/typescript-search-and-compile.sh" to execute this script
# (or "./typescript-search-and-compile.sh" if your terminal is in the folder the script is in)


# !!! CHANGE ME !!!
# location of your scripts root folder
# make sure that you do not add a trailing "/" at the end!!
# also, no spaces! If you have a space in the filepath, then
# you have to follow this link: https://stackoverflow.com/a/16703720/9800782
sr=~/path/to/scripts/root/folder
# !!! CHANGE ME !!!


# find all typescript config files
scripts=$(find $sr -name "tsconfig.json")


for s in $scripts
do
# strip off the word "tsconfig.json"
cd ${s%/*} # */ # this function gets incorrectly parsed by style linters on web
# run the typescript watch in the background
tsc -w &
# get the pid of the last executed background function
pids+=$!
# save it to an array
pids+=" "
done


# end all processes we spawned when you close this process
wait $pids

有用资源:

其他的答案在几年前可能是有用的,但是现在已经过时了。

假设一个项目有一个 tsconfig文件,运行以下命令..。

tsc --watch

... to watch for changed files and compile as needed. 文件解释说:

在监视模式下运行编译器。监视输入文件并在更改时重新编译触发器。监视文件和目录的实现可以使用环境变量配置。有关详细信息,请参阅 配置手表

为了回答最初的问题,即使在没有本机支持的平台上,递归目录监视也是可能的,正如 配置手表文档所解释的:

在本地不支持递归目录监视的平台上监视目录,通过使用 TSC _ watCHDIRECTORY 选择的不同选项递归地为子目录创建目录监视器来支持

在 linux 中我使用:

tsc -w $(find . | grep .ts)

This will watch every typescript file under the current directory.

当您使用 Ts-node-dev运行代码时,它将解决大多数问题

  1. ts-node-dev src/index.ts 将只编译其依赖项 JIT
  2. 关于更改重新编译和重新启动服务器