阮一峰 博客 ts.xcatliu.com
1.基本说明
我们知道,JavaScript 是一门非常灵活的编程语言。它没有类型约束,一个变量可能初始化时是字符串,过一会儿又被赋值为数字。
由于隐式类型转换的存在,有的变量的类型很难在运行前就确定。
基于原型的面向对象编程,使得原型上的属性或方法可以在运行时被修改。
函数是 JavaScript 中的一等公民[2],可以赋值给变量,也可以当作参数或返回值。
TypeScript是静态类型,指编译阶段就能确定每个变量的类型,这种语言的类型错误往往会导致语法错误。TypeScript在运行前需要先编译为 JavaScript,而在编译阶段就会进行类型检查;
而Javascript是动态类型,它是属于解释性语言,没有编译阶段。
2.弱类型。
允许隐式类型转换,这一点javascript是相同的。
3.安装:npm install -g typescript
创建:tsc hello.ts
我们约定使用 TypeScript 编写的文件以 .ts 为后缀,用 TypeScript 编写 React 时,以 .tsx 为后缀
4.TypeScript 编译的时候即使报错了,还是会生成编译结果javascript文件,我们仍然可以使用这个编译之后的文件。
如果要在报错的时候终止 js 文件的生成,可以在 tsconfig.json 中配置 noEmitOnError 即可!
5.基础
5.1原始数据类型:boolean,boolean 是 JavaScript 中的基本类型,而 Boolean 是 JavaScript 中的构造函数
number,string,void,unddefined,null,与 void 的区别是,undefined 和 null 是所有类型的子类型
其中 ` 用来定义 ES6 中的模板字符串,${expr} 用来在模板字符串中嵌入表达式
// 模板字符串
let sentence: string = `Hello, my name is ${myName}.
I'll be ${myAge + 1} years old next month.`;
5.2任意值
任意值(Any)用来表示允许赋值为任意类型。变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型
let myFavoriteNumber: any = 'seven';
myFavoriteNumber = 7;
5.3联合类型:联合类型(Union Types)表示取值可以为多种类型中的一种。
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
6.对象的类型:接口,在 TypeScript 中,我们使用接口(Interfaces)来定义对象的类型。
interface Person {
name: string;
age: number;
}
let tom: Person = {
name: 'Tom',
age: 25
};
6.1可选属性
有时我们希望不要完全匹配一个形状,那么可以用可选属性:
interface Person {
name: string;
age?: number;
}
let tom: Person = {
name: 'Tom'
};
6.2任意属性
interface Person {
name: string;
age?: number;
[propName: string]: any;
}
let tom: Person = {
name: 'Tom',
gender: 'male'
};
6.3只读属性:有时候我们希望对象中的一些字段只能在创建的时候被赋值,那么可以用 readonly 定义只读属性
注意,只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候
7.数组的类型
「类型 + 方括号」来表示数组
let fibonacci: number[] = [1, 1, 2, 3, 5];
数组泛型:我们也可以使用数组泛型(Array Generic) Array 来表示数组:
let fibonacci: Array = [1, 1, 2, 3, 5];
接口表示数组:
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
any 在数组中的应用:用 any 表示数组中允许出现任意类型
let list: any[] = ['xcatliu', 25, { website: 'xcatliu.com' }];
8.函数的类型
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
return x + y;
};
8.1可选参数:我们用 ? 表示可选的参数,可选参数后面不允许再出现必需参数了。
8.2剩余参数
function push(array, ...items) {
items.forEach(function(item) {
array.push(item);
});
}
let a: any[] = [];
push(a, 1, 2, 3);
8.3重载:重载允许一个函数接受不同数量或类型的参数时,作出不同的处理。
function reverse(x: number | string): number | string | void {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
9.类型断言,值 as 类型
interface Cat {
name: string;
run(): void;
}
interface Fish {
name: string;
swim(): void;
}
function isFish(animal: Cat | Fish) {
if (typeof (animal as Fish).swim === 'function') {
return true;
}
return false;
}
联合类型可以被断言为其中一个类型
父类可以被断言为子类
任何类型都可以被断言为 any
any 可以被断言为任何类型
10.声明文件:声明文件必需以 .d.ts 为后缀。
11.内置对象
进阶----------------------------------------------------------
12.类型别名:类型别名用来给一个类型起个新名字。我们使用 type 创建类型别名
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
if (typeof n === 'string') {
return n;
} else {
return n();
}
}
13.字符串字面量类型:我们使用 type 定了一个字符串字面量类型 EventNames,它只能取三种字符串中的一种。
type EventNames = 'click' | 'scroll' | 'mousemove';
function handleEvent(ele: Element, event: EventNames) {
// do something
}
handleEvent(document.getElementById('hello'), 'scroll'); // 没问题
handleEvent(document.getElementById('world'), 'dblclick'); // 报错,event 不能为 'dblclick'
14.元组:而元组(Tuple)合并了不同类型的对象
当直接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组类型中指定的项。
let tom: [string, number];
tom = ['Tom', 25];
15.枚举
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
常数枚举
const enum Directions {
Up,
Down,
Left,
Right
}
外部枚举
declare enum Directions {
Up,
Down,
Left,
Right
}
16.类
extends 继承:使用 extends 关键字实现继承,子类中使用 super 关键字来调用父类的构造函数和方法
static:使用 static 修饰符修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用:
abstract 用于定义抽象类和其中的抽象方法。抽象类是不允许被实例化的,抽象类中的抽象方法必须被子类实现
TypeScript支持接口继承类
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
interface Point3d extends Point {
z: number;
}
TypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。
public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的
private 修饰的属性或方法是私有的,不能在声明它的类的外部访问
protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的
17.泛型