类型别名
类型别名用来给一个类型起个新名字,类型别名常用于联合类型
type Name = string;type NameResolver = () => string;type NameOrResolver = Name | NameResolver;function getName(n: NameOrResolver): Name {if (typeof n === 'string') {return n;} else {return n();}}
上例中,我们使用 type 创建类型别名
字符串字面量类型
字符串字面量类型用来约束取值只能取三种字符串中的一种
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'// index.ts(7,47): error TS2345: Argument of type '"dblclick"' is not assignable to parameter of type 'EventNames'.
上例中,我们使用type定了一个字符串字面量类型EventNames,它只能取三种字符串中的一种。
注意:类型别名与字符串字面量类型都是使用type进行定义的。
元组
数组合并了相同类型的对象,而元组合并了不同类型的对象
// 定义一对值分别为string和number的元组let tom: [string, number] = ['Tom', 25];// 元组里元素和声明的类型要一一对应let jack: [string, number] = [26, 'jack']; // 报错
在赋值的时候也需要和声明的时候对应
let tom: [string, number];tom = ['Tom'];// Property '1' is missing in type '[string]'but required in type '[string, number]'.
元组每个位置数据类型必须一一对应,且不能空着;如果不想这样可以这样声明
let arr: Array<number | string> = ['1', 2, 3]
枚举
枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等。
枚举使用 enum 关键字来定义:
enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat }
枚举成员会被赋值从0开始递增的数字,同时也会对枚举值到枚举名进行反向映射:
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};console.log(Days["Sun"] === 0); // trueconsole.log(Days["Mon"] === 1); // trueconsole.log(Days["Tue"] === 2); // trueconsole.log(Days["Sat"] === 6); // trueconsole.log(Days[0] === "Sun"); // trueconsole.log(Days[1] === "Mon"); // trueconsole.log(Days[2] === "Tue"); // trueconsole.log(Days[6] === "Sat"); // true
手动赋值
enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};console.log(Days["Sun"] === 7); // trueconsole.log(Days["Mon"] === 1); // trueconsole.log(Days["Tue"] === 2); // trueconsole.log(Days["Sat"] === 6); // true
类
public、private和protected
- public哪里都可以访问
- private私有属性,不能在类外部访问,不能继承
- protect也不能在类外部访问,但可以继承 ```typescript class Animal { public name; public constructor(name) { this.name = name; } }
let a = new Animal(‘Jack’); console.log(a.name); // Jack a.name = ‘Tom’; console.log(a.name); // Tom
// 当name为私有属性时,不能再外部直接访问```typescriptclass Animal {private name;public constructor(name) {this.name = name;}}let a = new Animal('Jack');console.log(a.name); // Jacka.name = 'Tom';// index.ts(9,13): error TS2341: Property 'name' is private and only accessible within class 'Animal'.// index.ts(10,1): error TS2341: Property 'name' is private and only accessible within class 'Animal'.
抽象类
不允许被实例化,里面的方法必须被继承的子类来实现
下面这种情况就是子类没有实现抽象类的抽象方法sayHi从而引起的报错
abstract class Animal {public name;public constructor(name) {this.name = name;}public abstract sayHi();}class Cat extends Animal {public eat() {console.log(`${this.name} is eating.`);}}let cat = new Cat('Tom');// index.ts(9,7): error TS2515: Non-abstract class 'Cat' does not implementinherited abstract member 'sayHi' from class 'Animal'.
泛型
泛型是指在定义函数、接口或类的时候,不预先指定具体类型,而在使用的时候再指定类型的一种特性。
不好的实例写法
function createArray(length: number, value: any): Array<any> {let result = [];for (let i = 0; i < length; i++) {result[i] = value;}return result;}createArray(3, 'x'); // ['x', 'x', 'x']
上面的这段代码不会报错,但是一个显而易见的缺陷是,它并没有准确的定义返回值的类型;
Array
function createArray<T>(length: number, value: T): Array<T> {let result: T[] = [];for (let i = 0; i < length; i++) {result[i] = value;}return result;}createArray<string>(3, 'x'); // ['x', 'x', 'x']// 也可以 createArray(3, 'x');这样调用,让类型推论自动推算出来
函数名后添加了
