接口的作用是什么
- TypeScript 的核心原则之一是对值所具有的结构进行类型检查;
- 使用接口(Interfaces)来定义对象的类型;
- 接口是对象的状态(属性)和行为(方法)的抽象(描述);
- 一个类可继承另一个类,也可实现多个接口;
- 接口像插件一样用来增强类的,抽象类是具体类的抽象概念;
接口初探
// 定义接口
interface IPerson {
readonly id: number //只读成员,不能被修改
name: string
}
// 同名的接口可以写多少,类型会自动合并
interface IPerson {
age: number
sex: string
hooby?: string //可选成员
say: () => any
}
// 类型检查器会查看对象内部的属性是否与 IPerson 接口描述一致, 如果不一致就会提示类型错误
const person: IPerson = {
id: 1,
name: 'tom',
age: 20,
sex: '男'
}
任意类型
interface Cache {
name: string;
age: number;
// prop 可以改成任意值
[prop: string]: string | number; //动态成员
}
const cache: Cache = {
name: 'tom',
age: 20,
};
// 新增属性
cache.sex = '男';
cache.hobby = '唱、跳、rap';
类实现接口
interface Eat {
eat (food: string): void
}
interface Run {
run (distance: number): void
}
// 人
class Person implements Eat, Run {
eat (food: string): void {
console.log(`优雅的进餐: ${food}`)
}
run (distance: number) {
console.log(`直立行走: ${distance}`)
}
}
// 动物
class Animal implements Eat, Run {
eat (food: string): void {
console.log(`呼噜呼噜的吃: ${food}`)
}
run (distance: number) {
console.log(`爬行: ${distance}`)
}
}
接口的继承
interface Speakable {
speak(): void
}
interface SpeakChinese extends Speakable {
speakChinese(): void
}
class ChineseMan implements SpeakChinese {
speakChinese(): void {
throw new Error("Method not implemented.")
}
speak() {
throw new Error("Method not implemented.")
}
}
函数类型接口
interface Discount {
(price: number): number
}
const discount: Discount = (price: number): number => {
return price * .8;
}
构造函数接口
interface AClass {
new(name: string): any // 描述类的构造函数
}
class Animal {
constructor(public name: string) { }
}
let aFun: AClass = Animal
可索引接口
interface User {
// 这个 index 可以随便写
[index: number]: string | number
}
// 约束对象
let user: User = { 0: '0', 1: '1', 2: '2', 3: 3 };
// 约束数组
let arr: User = ['1', '2', '3', 6];
type 类型别名
type 作用就是给类型起一个新名字,支持基本类型、联合类型、元祖及其它任何需要的手写类型,常用于联合类型;
type test = number; //基本类型
let num: test = 10;
type userOjb = { name: string }; // 对象
type getName = () => string; // 函数
type data = [number, string]; // 元组
type numOrFun = Second | getName; // 联合类型
// 拿到 T1 的所有属性名联合类型、拿到 T1 所有属性值类型的联合类型
type T1 = { delay: "One"; setMessage: "Two" };
type K1 = keyof T1; // T1 的 key 组成的联合类型 'delay' | 'setMessage'
type V1 = T1[K1]; // V1 就是 T1 的值 的联合类型 "One" | "Two"
interface 与 type 的异同
不同点
- type 和 interface 的语法不一样;
- 定义的类型上:
- interface 主要声明的是函数和对象,并且总是需要引入特定的类型;
- type 声明的可以是任何的数据类型(基本类型别名,联合类型,元组等类型);
- 扩展的方式不一样:
- interface 可以使用 extends 关键字来进行扩展(这个继承是包含关系,如果父级有了,子集不可以声明重复的,会报错的),或者是 implements 来进行实现某个接口;
- type 也可以进行扩展,使用 & 符号进行(这个继承是合并关系,如果父级有了一个类型,子集还可以声明)这个叫做 交叉类型;
- 合并声明:
- interface 可以定义一个名字,后面的接口也可以直接使用这个名字,自动合并所有的声明,但是不建议这么使用,还是使用 extends 关键字;
- type 不能这么使用,会直接报错;
- 实例类型进行赋值:
- interface 没有这个功能;
- type 可以使用 typeof 获取实例的 类型进行赋值;
- 类型映射:
- interface 没有这个功能
- type 可以通过 in 来实现类型映射;
- 最大的不同:interface 可以被类实现,而 type 不可以;
相同点
- 两者都不会出现在编译结果里面;
- 两者都可以进行扩展,只是拓展的方式不一样;
- 两者都可以描述函数和对象;
装饰器
上一篇