TypeScript 入门

TypeScript 是一种由微软开发的自由和开源的编程语言,它是JavaScript的一个超集,扩展了JavaScript的语法。

以下是常用的几种语法特性:

类型注解

TypeScript里的类型注解是一种轻量级的为函数或变量添加约束的方式。 在这个例子里,我们希望greeter函数接收一个字符串参数。 如果此时把greeter的调用改成传入一个数组,编译时将会产生错误

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

let user1 = [0, 1, 2];
let user2 = "Jack";

document.body.innerHTML = greeter(user1); // 错误
document.body.innerHTML = greeter(user2); // 正确

接口

让我们开发这个示例应用。这里我们使用接口来描述一个拥有firstName和lastName字段的对象。 在TypeScript里,只在两个类型内部的结构兼容那么这两个类型就是兼容的。 这就允许我们在实现接口时候只要保证包含了接口要求的结构就可以,而不必明确地使用implements语句。

1
2
3
4
5
6
7
8
9
10
11
12
interface Person {
firstName: string;
lastName: string;
}

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

let user = { firstName: "Jane", lastName: "User" };

document.body.innerHTML = greeter(user);

最后,让我们使用类来改写这个例子。 TypeScript支持JavaScript的新特性,比如支持基于类的面向对象编程。

让我们创建一个Student类,它带有一个构造函数和一些公共字段。 注意类和接口可以一起共作,程序员可以自行决定抽象的级别。

还要注意的是,在构造函数的参数上使用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);

在React中使用TypeScript

下面我们将要创建一个Hello组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// src/components/Hello.tsx

import * as React from 'react';

export interface Props {
name: string;
enthusiasmLevel?: number;
}

function Hello({ name, enthusiasmLevel = 1 }: Props) {
if (enthusiasmLevel <= 0) {
throw new Error('You could be a little more enthusiastic. :D');
}

return (
<div className="hello">
<div className="greeting">
Hello {name + enthusiasmLevel}
</div>
</div>
);
}

注意我们定义了一个类型Props,它指定了我们组件要用到的属性。 name是必需的且为string类型,同时enthusiasmLevel是可选的且为number类型(你可以通过名字后面加?为指定可选参数)。

我们创建了一个无状态的函数式组件(Stateless Functional Components,SFC)Hello。 具体来讲,Hello是一个函数,接收一个Props对象并拆解它。 如果Props对象里没有设置enthusiasmLevel,默认值为1。

也可以用类的方式定义该组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Hello extends React.Component<Props, object> {
render() {
const { name, enthusiasmLevel = 1 } = this.props;

if (enthusiasmLevel <= 0) {
throw new Error('You could be a little more enthusiastic. :D');
}

return (
<div className="hello">
<div className="greeting">
Hello {name + enthusiasmLevel}
</div>
</div>
);
}
}

当我们的组件具有某些state的时候,使用类的方式是很有用处的。 但在这个例子里我们不需要考虑state。事实上,在React.Component<Props, object>我们把state指定为了object,因此使用SFC更简洁。

调用该组件:

1
<Hello name="TypeScript" enthusiasmLevel={10} />