TypeScript+React 实践

一些概念

TypeScript

强类型的 javascript

React

利用 jsx 实现 web 开发的组件化。

d.ts 文件

d.ts 文件是 typescript 的类型定义文件,ts 依靠这个文件来为 js 代码中的类型添加类型说明并提供类型检查
所有的类型定义文件基本都可以在这里找到

typings

https://github.com/typings/typings
typings 是一个 typescript 的类型定义管理工具,可以使用它来安装 js 框架的 d.ts 类型定义文件,这样在 ts 项目中使用 js 框架时候就会得到准确的类型定义。

准备工作

材料
node
npm

建立项目的目录结构

1
2
3
4
5
proj/
├─ src/
| └─ components/
|
└─ dist/

初始化 npm

1
$ npm init`

搭建开发环境

0x01 安装 typescript 和 webpack

在全局安装 typescript 和 webpack

1
$ npm install -g typescript webpack

0x02 安装 react 和 react-dom

1
$ npm install --save react react-dom @types/react @types/react-dom

0x03 安装开发依赖

1
2
$ npm install --save-dev ts-loader source-map-loader
$ npm link typescript

这里安装 ts-loader 用于调用 tsc 来根据 tsconfig.json 编译 .ts 文件,输出 .js 文件,source-map-loader 它会根据 tsc 编译生成的 ts<->js sourcemap 文件生成 webpack 的 sourcemap 文件。

npm link 可以让 ts-loader 直接使用全局的 tsc 来编译 ts 文件,这样就无须在项目目录下单独安装 typescript。

0x04 HelloWorld

在 src 目录下新建 index.tsx 文件,键入如下内容

index.tsx

1
2
3
4
5
6
7
8
9
import * as React from "react";
import * as ReactDOM from "react-dom";

import { Hello } from "./components/Hello";

ReactDOM.render(
<Hello compiler="TypeScript" framework="React" />,
document.getElementById("example")
);

在 src/components 目录下新建一个 Hello 组件

Hello.tsx

1
2
3
4
5
6
7
8
9
import * as React from "react";

export interface HelloProps { compiler: string; framework: string; }

export class Hello extends React.Component<HelloProps, {}> {
render() {
return <h1>Hello from {this.props.compiler} and {this.props.framework}!</h1>;
}
}

最后在根目录下面创建 index.html 文件
index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
</head>
<body>
<div id="example"></div>
<script src="./node_modules/react/dist/react.js"></script>
<script src="./node_modules/react-dom/dist/react-dom.js"></script>
<script src="./dist/bundle.js"></script>
</body>
</html>

0x05 编写 tsconfig.json

在根目录下新建 tsconfig.json 文件,键入以下内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es5",
"jsx": "react"
},
"files": [
"./src/components/Hello.tsx",
"./src/index.tsx"
]
}

0x06 配置 webpack

同样在根目录下创建 webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js",
path: __dirname + "/dist"
},

devtool: "source-map",

resolve: {
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},

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

preLoaders: [
{ test: /\.js$/, loader: "source-map-loader" }
]
},

externals: {
"react": "React",
"react-dom": "ReactDOM"
},
};

0x07 run

执行

1
$ webpack

一些坑

没有 d.ts

有一些开源的 js 框架没有现成的 d.ts 类型定义文件,这就导致在 ts 中使用这些框架会编译不通过。

如果框架是类似 jQuery 这种内容都被封装在一个全局变量中的框架来讲,以 jquery 为例只需要在html中引用文件,并在使用到框架的地方为对象添加 any 的类型说明就可以使用了。

1
2
3
import 'jquery'

declare var jquery: any, $: any;

但是对于非封装到一个全局变量中的框架,就比较麻烦了。需要自己编写类型说明,这里还没有比较好的办法。编写类型定义文件的方法在这里

使用 npm 安装的 types 会报错

问题:
“@types/react”: “^0.14.44”,
“@types/react-dom”: “^0.14.18”,
在项目中使用这两个版本的类型定义文件编译时会报错。

解决方案:
不要使用 npm 安装 types 直接使用 typings 安装需要的 js 框架的类型定义文件,然后在编译选项中引入这些声明文件。
参见: TYPESCRIPT项目和TSCONFIG.JSON
或者直接升级至以下版本
“@types/react”: “^0.14.52”,
“@types/react-dom”: “^0.14.19”,

参考:

  1. http://to-u.xyz/2016/05/26/webpack-react-multiplePage/
  2. https://react-bootstrap.github.io/components.html
  3. https://www.typescriptlang.org/docs/handbook/react-&-webpack.html
  4. http://blog.csdn.net/kinfey/article/details/50387534