# 从 JavaScript 迁移

# 设置目录

如果你在写纯 JavaScript,你大概是想直接运行这些 JavaScript 文件, 这些文件存在于 src,lib 或 dist 目录里,它们可以按照预想运行。

你可能还需要对 JavaScript 做一些中间处理,比如合并或经过 Babel 再次编译。 在这种情况下,你应该已经有了如下的目录结构。

那么现在,我们假设你已经设置了这样的目录结构:

projectRoot
├── src
│   ├── file1.js
│   └── file2.js
├── built
└── tsconfig.json

# 配置文件

TypeScript 使用 tsconfig.json 文件管理工程配置,例如你想包含哪些文件和进行哪些检查。 让我们先创建一个简单的工程配置文件:

{
  "compilerOptions": {
    "outDir": "./built",
    "allowJs": true,
    "target": "es5"
  },
  "include": ["./src/**/*"]
}

这里我们为 TypeScript 设置了一些东西:

  1. 读取所有可识别的 src 目录下的文件
  2. 接受 JavaScript 做为输入
  3. 生成的所有文件放在 built 目录下
  4. 将 JavaScript 代码降级到低版本比如 ECMAScript 5

tsc
├── built
|  ├── file1.js
|  └── file2.js
├── src
|  ├── file1.js
|  └── file2.js
└── tsconfig.json

# 与构建工具进行集成

Webpack 集成非常简单。 你可以使用 ts-loader,它是一个 TypeScript 的加载器,结合 source-map-loader 方便调试。 运行:

npm install ts-loader source-map-loader
module.exports = {
  // ...

  // Enable sourcemaps for debugging webpack's output.
  devtool: "source-map",
  module: {
    loaders: [
      // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
      { test: /\.tsx?$/, loader: "ts-loader" }
    ],

    preLoaders: [
      // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
      { test: /\.js$/, loader: "source-map-loader" }
    ]
  }
  // ...
};

要注意的是 ts-loader 必须在其它处理.js 文件的加载器之前运行。

{ test: /\.tsx?$/, loader: ["babel-loader", "ts-loader"] }

# 转换到 TypeScript 文件

到目前为止,你已经做好了使用 TypeScript 文件的准备。 第一步,将 .js 文件重命名为.ts 文件。 如果你使用了 JSX,则重命名为 .tsx 文件。

当然了,你可能感觉哪里不对劲儿。你可能会看到有些行上有红色的波浪线。你可以把它们当做在 Microsoft Word 里看到的红色波浪线一样。 但是 TypeScript 仍然会编译你的代码,就好比 Word 还是允许你打印你的文档一样。

# 去除错误

我们提到过,若不出所料,在转换后将会看到错误信息。 重要的是我们要逐一的查看它们并决定如何处理。 通常这些都是真正的 BUG,但有时必须要告诉 TypeScript 你要做的是什么。

# 由模块导入

首先你可能会看到一些类似 Cannot find name 'require'.和 Cannot find name 'define'.的错误。 遇到这种情况说明你在使用模块。 你仅需要告诉 TypeScript 它们是存在的:

// For Node/CommonJS
declare function require(path: string): any;
// For RequireJS/AMD
declare function define(...args: any[]): any;
最好是避免使用这些调用而改用TypeScript的导入语法。

最好是避免使用这些调用而改用 TypeScript 的导入语法。

import foo = require("foo");

foo.doStuff();

# 获取声明文件

如果你开始做转换到 TypeScript 导入,你可能会遇到 Cannot find module 'foo'.这样的错误。 问题出在没有 声明文件来描述你的代码库。 幸运的是这非常简单。 如果 TypeScript 报怨像是没有 lodash 包,那你只需这样做

npm install -s @types/lodash

这得益于一个开源项目 types (opens new window)

# 由模块导出

通常来讲,由模块导出涉及添加属性到 exports 或 module.exports。 TypeScript 允许你使用顶级的导出语句。 比如,你要导出下面的函数:

部分导出

module.exports.feedPets = function (pets) {
  // ...
};
export function feedPets(pets) {
  // ...
}

完全导出

function foo() {
  // ...
}
module.exports = foo;
function foo() {
  // ...
}
export = foo;