类型别名
类型别名用来给一个类型起个新名字
//使用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();
}
}
字符串字面量类型
用来约束取值只能是某几个字符串中的一个。
//也是使用type来定义的
type EventNames = 'click' | 'scroll' | 'mousemove';
function handleEvent(ele: Element, event: EventNames) {
// do something
}
handleEvent(document.getElementById('hello'), 'scroll'); // 没问题
handleEvent(document.getElementById('world'), 'dbclick'); // 报错,event 不能为 'dbclick'
元组
数组合并了相同类型的对象,而元组合并了不同类型的对象。
枚举
枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只有七天。
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
//枚举成员会被赋值为从0开始递增的数字
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true
console.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true
常数项和计算所得项
枚举项有两种类型: 常数项和计算所得项
enum Color {Red, Green, Blue = "blue".length}
常数枚举
常数枚举是使用 const enum定义的枚举类型
const enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
外部枚举
declare enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
类
JavaScript通过构造函数实现类的概念,通过原型链实现继承。ES6中使用了class
类相关的概念:
- 类: 定义了一件事物的抽象特点,包含它的属性和方法
- 对象: 类的实例,通过new生成
- 面向对象(OOP)的三大特性: 封装, 继承, 多态
- 多态: 由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。
- 修饰符: 一些关键字,用于限定成员或类型的性质,比如
public - 抽象类: 抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现
- 接口: 不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现,一个类只能继承自另一个类,但是可以实现多个接口。
TypeScript中类的用法
ts可以使用三种访问修饰符,分别是public, private和protected
public: 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的
private: 修饰的属性或方法是私有的,不能在声明它的类的外部访问
protected: 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的
class Animal {
private name;
public constructor(name) {
this.name = name;
}
}
let a = new Animal('Jack');
console.log(a.name); // Jack
a.name = 'Tom';
抽象类
abstract用于定义抽象类和其中的抽象方法。
- 抽象类不允许被实例化
- 抽象类中的抽象方法必须被子类实现
abstract class Animal {
public name;
public constructor(name) {
this.name = name;
}
public abstract sayHi();
}
let a = new Animal('Jack'); //报错
class Cat extends Animal {
public eat() {
console.log(`${this.name} is eating.`);
}
}
let cat = new Cat('Tom'); //报错,因为没有实现抽象方法sayHi
给类加上ts的类型
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
sayHi(): string {
return `My name is ${this.name}`;
}
}
let a: Animal = new Animal('Jack');
console.log(a.sayHi()); // My name is Jack
类与接口
接口可以用于对对象的形状进行描述,也可以对类的一部分行为进行抽象。
类实现接口
interface Alarm {
alert();
}
class Door {
}
class SecurityDoor extends Door implements Alarm {
alert() {
console.log('SecurityDoor alert');
}
}
class Car implements Alarm {
alert() {
console.log('Car alert');
}
}
一个类可以实现多个接口
interface Alarm {
alert();
}
interface Light {
lightOn();
lightOff();
}
class Car implements Alarm, Light {
alert() {
console.log('Car alert');
}
lightOn() {
console.log('Car light on');
}
lightOff() {
console.log('Car light off');
}
}
接口继承接口
interface Alarm {
alert();
}
interface LightableAlarm extends Alarm {
lightOn();
lightOff();
}
接口继承类
class Point {
x: number;
y: number;
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};
泛型
泛型是指在定义函数, 接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
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']
上面代码的缺陷就是它没有准确的定义返回值得类型。
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']
我们在函数名后添加了 ,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array 中即可使用了。