如果你还不了解 TypeScript 是什么,或者其与 JavaScript 之前的关系,可以参考:- 前后端常用概念扫盲

TypeScript 是 JavaScript 的一个超集,支持 ES6 的语法规范,并在此基础上进行了增强,二者最大的不同在于:TypeScript 是强类型语言,而 JavaScript 是弱类型的语言。

本文将着重介绍二者的不同之处。

一、变量声明

TypeScript 支持使用varletconst进行变量声明,但建议不要使用var
TypeScript 声明变量时,可以强制指定变量类型或者由编译器自动从“值”推导出变量类型,但无论哪种情况,一旦确定了类型,后面不能再次被赋值为其他类型:

1
2
3
4
5
6
7
8
9
let a = 1;
a = 10;
a = "x"; ❌

let b : number = 12;
let c : number = "x"; ❌

let fibonacci: number[] = [1, 1, 2, 3, 5];
let fibonacci: number[] = [1, '1', 2, 3, 5];❌

二、函数参数

TypeScript 要求:调用函数时传入的参数必须与函数声明的参数一致(个数及类型),如:

1
2
3
4
5
6
function sum(x: number, y: number): number {
return x + y;
}
sum(1, 2, 3); ❌
sum(1);❌
sum(1, "x"); ❌

TypeScript 要求:可选参数必须在参数列表的最后,如:

1
2
3
4
5
6
7
function buildName(firstName?: string, lastName: string) {❌
if (firstName) {
return firstName + ' ' + lastName;
} else {
return lastName;
}
}

三、枚举

枚举是 TypeScript 特有的:
第一个元素没有赋值,则默认为 0,后面的元素的值依此递增:

1
2
3
4
5
6
7
8
9
enum Days {
Sun, // 0
Mon, // 1
Tue, // 2
Wed,
Thu,
Fri,
Sat
};

也支持:

1
2
3
4
5
6
7
8
9
enum Days {
Sun = 1, // 1
Mon, // 2
Tue, // 3
Wed = 10, // 10
Thu, // 11
Fri, // 12
Sat // 13
};

枚举元素可以是常量值或是可以通过编译期计算得出的值:

1
2
3
4
5
6
7
8
9
enum FileAccess {
// 常量值
None, // 0
Read = 1 << 1,
Write = 1 << 2,
ReadWrite = Read | Write,
// 计算得出的值
G = "123".length
}

四、类

相比ES6TypeScript新增了继承、成员访问控制修饰符。越来越有 Java、C++的味道了。

4.1 继承、成员访问控制修饰符

TypeScript 继承需要使用extends关键字,只支持单继承,这点不同于 C++。
类继承后,子类可以重写父类的方法。

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
29
30
31
32
33
34
35
36

class Person {
private id: string; // 私有的,只能被自身访问

protected name: string; // 受保护,可以被其自身以及其子类和父类访问
protected age: number; // 公开的

public getId() : string {
return this.id;
}

public getName() : string {
return this.name;
}

public getAge() : number {
return this.age;
}

public print() : void {
console.log("name:" + this.name + ", age:" + this.age);
}
}

class Student extends Person {
private grade : number;

public getGrade() : number {
return this.grade;
}

public print() : void { // 重写了父类的方法
super.print(); // 使用super直接调用父类方法
console.log("grade:" + this.grade);
}
}

4.2 instanceof

instanceof 运算符用于判断对象是否是指定的类型,如果是返回true,否则返回false

1
2
3
class Person {}
let obj = new Person();
let isPerson: boolean = obj instanceof Person;

4.3 interface 接口

TypeScript 新增 interface 接口的概念,这个接口的概念和 Java 中的 interface 类似,即:只有定义没有实现。

同时,接口也支持继承。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface IPerson {
name: string;
}

interface IStudent extends IPerson {
// 接口的继承
grade: number;
}

class Student implements IStudent {
// 实现接口的类
name: string;
grade: number;
}

五、命名空间

TypeScript 中的命名空间的概念和 C++中的命名空间的概念一样,而且关键字也都是namespace

稍有不同的是,C++不需要将命名空间中的内容暴露出来,C++默认就是全部暴露的,而 TypeScript 需要手动添加 export 关键字将命名空间的中的内容暴露出来:

1
2
3
4
5
6
7
8
9
10
namespace XYZ {
export let name : string;
export class Person {
}

export interface IPerson {
}
}

XYZ.name = "jeff";