泛型(Generics)
泛型,就是在定义函数、接口或者类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
// 函数功能:接收用户输入,得到一个指定长度的数组,数组元素类型取决于输入的值的类型
// 这种写法并不好,并不知道最后返回值类型(any)
function create(length: number, value: any): Array<any> {
let result: any[] = []
for(let i = 0; i<length; i++) {
result[i] = value
}
return result
}
// 改用泛型
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()函数中,我们在函数名后面加上了< T >,用以指代任意输入的类型。
类型别名
类型别名用来给一个类型起一个新名字。type 别名 = 数据类型
字符串字面量
字符串字面量类型,用来约束取值只能是某几个字符串中的一个。
type EventNames = 'click' | 'scroll'
function handleEvent(ele: HTMLElement | null, event: EventNames) {
console.log('666');
}
// 这两种写法没有错误
handleEvent(document.querySelector('a') as HTMLElement, 'scroll')
handleEvent(document.getElementById('hello'), 'click')
// handleEvent(document.getElementById('div') as HTMLElement, 'mousemove') 报错,第二个参数不可以是mousemove
元组
元组是合并了不同类型的对象的一种数据类型。与之类似的是数组,它合并了相同类型的对象。
它的声明方式与数组几乎无异,只不过在元组中,类型声明显得尤为重要。
// 如下即声明了一个元组:一对值为string、number的元组
let mar: [string, number] = ['Mar', 28]
// 访问元组的元素:索引下标访问即可
console.log(mar[0]);
console.log(mar[1]);
元组并非只能有两个元素,当向其中添加越界元素时,会受到类型限制。
// 此时,若向mar中再添加元素,添加的第一个只能是字符串,第二个只能是number
mar.push('Hah')
mar.push(90)
枚举
Enum类型用于取值被限定在·一定范围内的场景。
与C语言中的枚举类型几乎一致,使用enum关键字,语法格式如:enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat }
枚举成员会被赋值为从0开始递增的数字,同时也会对枚举值到枚举名进行反向映射。
enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat }
console.log(Days["Sun"])
console.log(Days[0])
console.log(Days["Sat"] === 6)
类
基本介绍
类是在ES6中引入的,此后,JavaScript也有了class关键字,用于声明一个类了。
简单介绍ES6以来,类的一些用法:
- 首先,这里的class体现的是面向对象,和Java、c++中的面向对象几乎一致,都具有封装、继承、多态三大特性,此外也有存取器、修饰符、抽象类、接口等概念;
- 类中具有方法、属性且实例的属性可以直接在类里面定义(ES7);
- extends关键字用于实现继承,子类中使用super关键字来调用父类的构造函数(类似Java);
- 类中也具有静态属性、静态方法,它们都可以直接通过类名来调用;
- 参数属性具有简便写法,修饰符可以出现在构造函数参数中,用于直接赋值;
- 只读属性关键字readonly,可以使属性不可以被修改;
- abstract关键字,用于声明抽象类
类与接口
接口不仅可以用于声明对象的形状,还可以对类的一部分行为进行抽象。
一般来说,在javascript中,一个类最多只能继承自一个类,但是如果要真的有继承多个类的打算,就需要单独将它们做成接口,然后分别实现。
比如,对于一般的车,假设只有行驶(run)功能:
class Car {
run() {
console.log('I can run.');
}
}
要想让它实现接口,如下书写即可:
// 类与接口
// 接口:可以警鸣
interface Alarmable {
alert(): void
}
interface Lightable {
lighten(): void
}
// 类:车
class Car implements Alarmable, Lightable {
run() {
console.log('I can run.');
}
alert(): void {
console.log('I can alert!');
}
lighten(): void {
console.log('I can lighten everything!');
}
}
声明合并
即:如果定义了两个相同名字的函数、接口或者类,那么它们会合并成一个类型。
下面演示接口的合并:
// 如下两个接口声明可以合并
interface Foldable {
price: number
}
interface Foldable {
weight: number
}