类型别名
类型别名用来给一个类型起个新名字,类型别名常用于联合类型
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); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true
console.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true
console.log(Days[2] === "Tue"); // true
console.log(Days[6] === "Sat"); // true
手动赋值
enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"] === 7); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.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为私有属性时,不能再外部直接访问
```typescript
class Animal {
private name;
public constructor(name) {
this.name = name;
}
}
let a = new Animal('Jack');
console.log(a.name); // Jack
a.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 implement
inherited 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');这样调用,让类型推论自动推算出来
函数名后添加了