0%

TypeScript 从入门到放弃之快速入门

前言

尝试了一下 TypeScript 之后,是“真香”啊,静态类型检验确实能避免很多编译时的问题。学有余力之际,所以打算先过一遍官方文档。本系列是以官方文档为主,结合自身相关经验整理而成的入门学习笔记。

TypeScript 速览

安装 TypeScript

1
$ npm install -g typescript

编译

1
2
3
4
5
6
7
8
// greeter.ts
function greeter(person) {
return "Hello, " + person;
}

let user = "Jane User";

document.body.innerHTML = greeter(user);
1
$ tsc greeter.ts

编译后会得到同名的 js 文件。

类型注解(Type annotations)

1
2
3
4
5
6
7
function greeter(person: string) {
return "Hello, " + person;
}

let user = "Jane User";

document.body.innerHTML = greeter(user);

加上注解(其实,不加类型注解,变量类型应该是 any )后,编译会经过类型检查,不正确会报错,但是仍然会生成相应的 js 文件。

接口(Interfaces)

描述对象字段类型。只要对象包含接口中的必须字段即可,多余字段不做检查。

类(Classes)

可包含公有变量和构造器。值得注意的是,构造函数的参数上使用 public 等同于创建了同名的成员变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Student {
fullName: string;
constructor(public firstName: string, public middleInitial: string, public lastName: string) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
}

interface Person {
firstName: string;
lastName: string;
}

function greeter(person: Person) {
return "Hello, " + person.firstName + " " + person.lastName;
}

let user = new Student("Jane", "M.", "User");

document.body.innerHTML = greeter(user);

例如本例中,编译后得到的结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var Student = /** @class */ (function () {
function Student(firstName, middleInitial, lastName) {
this.firstName = firstName;
this.middleInitial = middleInitial;
this.lastName = lastName;
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
return Student;
}());
function greeter(person) {
return "Hello, " + person.firstName + " " + person.lastName;
}
var user = new Student("Jane", "M.", "User");
document.body.innerHTML = greeter(user);

如果去掉 middleInitialpublic 修饰,则 this.middleInitial = middleInitial; 会被移除。

运行 TypeScript Web 应用

新建如下 greeter.html

1
2
3
4
5
6
7
<!DOCTYPE html>
<html>
<head><title>TypeScript Greeter</title></head>
<body>
<script src="greeter.js"></script>
</body>
</html>

使用浏览器打开,可得输出

1
Hello, Jane User

快速入门

官方提供了基于多种框架的入门教程,这里列一下我知名知意的教程

因为我是从 React 入手 TypeScript 的,故仅作基于 React 入门笔记。

TypeScript React 入门

安装 create-react-app

1
$ npm install -g create-react-app

创建新项目

1
$ create-react-app my-app --scripts-version=react-scripts-ts

react-scripts-ts is a set of adjustments to take the standard create-react-app project pipeline and bring TypeScript into the mix.

我的理解是 react-scripts-ts 是一个给标准的 create-react-app 项目混合 TypeScript 支持的管道。

关于目录结构的说明,详见官方文档

代码管理

1
2
3
$ git init
$ git add .
$ git commit -m "Initial commit."

重写默认 TSLint 配置( tslint.json / tslint.yaml )

由于 react-scripts-ts 预设的配置有些过于热心(a bit overzealous,还真不知道怎么翻译好),所以修改如下。

1
2
3
4
5
6
7
8
9
10
11
{
- "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
+ "extends": [],
+ "defaultSeverity": "warning",
"linterOptions": {
"exclude": [
"config/**/*.js",
"node_modules/**/*.ts"
]
}
}

关于配置 TSLint,这个作为补充,为了定制化配置,需要研究下。

启动

1
$ npm run start

测试

1
$ npm run test

所有以 .test.tsspec.ts 的文件,都会被 Jest 运行。特别的, Jest 也会像 npm run start 一样自动运行。

编译

1
$ npm run build

创建一个组件

通过类创建的组件可以使用状态和生命周期函数,由于 React 16.8 之后提供的 hooks ,我们已经可以在函数式组件中使用一些特殊功能,包括状态管理。

偶然看到一个讨论 React 16.7 - React.SFC is now deprecated ,进而找到 Rename React’s SFC to ‘FunctionalComponent’,官方已经修改了 SFC 定义 _(:3J∠)_

类型断言(Type assertions)

类似这样 document.getElementById('root') as HTMLElementas 语法,被称为类型断言,或者类型转换。这是一个非常重要的方式去告诉类型检查器( type checker )我们使用的对象究竟是什么类型。

举个例子,定义一个 CommentType 的类型,当我们从后台请求了响应的评论列表 comments 时,就可以使用如下的方式告诉类型检查器我们得到的是一个 CommentType 数组。

1
2
3
4
5
declare type CommentType = {}

// ...

comments as CommentType[]

这里 getElementById 的返回类型是 HTMLElement | null,所以我们使用 as 语法让 TypeScript 确信为 HTMLElement 类型。

状态组件

为状态组件添加类型校验的使用方式如下:

1
2
3
4
5
6
7
8
9
10
11
interface HelloProps {
name: string;
}

interface HelloState {
current: string;
}

class Hello extends React.Component<HelloProps, HelloState> {
// ...
}

备注:

添加样式

和通常的方式一致。

使用 Jest 编写测试

首先,需要安装 EnzyMe 。默认情况下,应用包含了一个叫 jsdom 的库,用于模拟 DOM 树并测试其运行时行为。 EnzyMe 是基于 jsdom 的让用户更为简单的访问组件的行为。

1
$ npm install -D enzyme @types/enzyme enzyme-adapter-react-16 @types/enzyme-adapter-react-16 react-test-renderer

关于配置和入门使用,参阅本节官方文档

添加状态管理器

介绍了 ReduxMobX,并基于 Redux 做了较为详细的讲解。如果都在看 TS 的文档了,状态管理应该已经很熟悉了吧,这里著作赘述了。

弹出配置

如果想自定义 create-react-app 的配置,需要用到弹出配置的功能。

1
$ npm run eject

在学习 ant-design 的时候,接触到了 react-app-rewired ,可以在不弹出配置的情况下重写相关配置,个人觉得通常情况下这个应该是个不错的选择。

下一步

多学习 React 官方文档,还有很多其他的技术需要学习,诸如状态管理,项目配置,页面路由等等…