跳到主要内容

Interface

声明类型

interface的基本用法还是用来声明类型

定义对象

interface通常用于定义对象的类型,语法格式如下,属性之间定义的类型通过英文分号间隔;

interface <interface name> {
property1: <type name>;
property2: <type name>;
...
}

从 TypeScript 官网的介绍:

One of TypeScript’s core principles is that type checking focuses on the shape that values have. This is sometimes called “duck typing” or “structural subtyping”.

TypeScript 的核心之一就是根据值的形状进行类型检查,称为鸭式辩型

所以interface就是根据对象的“形状”去判断其类型,使用interface声明的对象类型,TypeScript 只会检查是否至少存在所需的属性并与所需的类型所匹配,并且不需要保证顺序

interface LabeledValue {
label: string;
}

function printLabel(labeledObj: LabeledValue) {
console.log(labeledObj.label);
}

// 可以设置额外的属性,但是要保证在interface中声明的必须属性要存在
let myObj = { size: 10, label: 'Size 10 Object' };
printLabel(myObj);

可选属性

如果一个属性可有可无,这在 React 的 Props 中十分常见,那么可以在属性名称后面紧跟一个 ?来标识:

interface SquareConfig {
color?: string;
width?: number;
}

只读属性

如果禁止其它地方在使用对象属性的时候去修改它,可以在属性名前面添加readonly属性

interface Point {
readonly x: number;
readonly y: number;
}

readonly只用于对象属性,如果要求变量值不发生改变,使用const

索引类型

可索引类型具有一个索引签名,描述了对象索引的类型;在 JS 中,可以通过方括号语法[]来访问对象属性值,或者来访问数组元素。所以在 TypeScript 中可索引类型只具有两种类型:stringnumber

当不确定对象要包含什么属性的时候,就可以通过interface声明一个可索引类型来表示一个对象,[]内表示的是属性的类型,由于是对象,所以固定是string,方括号后面的:指定属性值的类型,使用该类型的对象的属性值必须每一个都匹配指定的类型。例如:

interface Obj {
[propName: string]: string;
}

let obj: Obj = {
name: 'oxygen',
};

当然了,也可以用来表示一个数组类型,不过数组的索引都是number,方括号后面依旧是紧跟:加元素的类型

interface StringArray {
[index: number]: number;
}

let arr: StringArray = [23];

定义函数

interface同样可以用于单独指定函数的参数和返回值类型,在interface中定义的函数参数名称和实际使用的函数参数名称并不要求相同;常见的写法是先使用interface声明函数的参数和返回值类型,然后定义函数的时候指定其类型为interface声明的类型。

interface Func {
(name: string, age: number): string;
}

// 这里声明的函数的参数名和上面interface内指定的参数名并不需要相同
const func: Func = (name, age) => {
return `I am ${name}, ${age} years old.`;
};

func('oxygen', 23);

对象方法

如果一个函数定义在对象属性中,那么这个函数可以被称为这个对象的方法。也就是对象的属性如果是一个函数,那么就需要指定其为函数类型

interface Person {
age: number;
getName: (name: string) => string; //定义对象内部的方法
}

const person: Person = {
age: 20,
getName: name => {
return name;
},
};

person.getName('oxygen');

定义数组

interface通过方括号[]index指定索引的类型可以声明一个数组类型;指定给index的类型只能是number或者string,我个人感觉这种方法比较麻烦

interface Person {
[index: number]: string;
}

const persons: Person = ['a', 'b', 'c', 'd'];
console.log(persons[1]);

定义 class

interface可以用于定义class中的属性,方法等类型;在定义类的时候,通过implements(实现)实现定义的interface即可

interface IPerson {
name: string;
getAge: (age: number) => number;
}

class Person implements IPerson {
name = 'oxygen';

getAge = (age: number) => {
return age;
};
}

const person = new Person();
console.log(person.name); // oxygen

继承

通过extends关键字可以将几个声明的interface组合起来,也可称为继承。

interface House {
room: number;
price: number;
}

interface MyHouse extends House {
people: number;
}

实现

通过implements关键字可以通过class实现interface内部定义的属性,方法等,这在 OOP 语言中表现为多态性:同一个接口下的不同表现形式。

interface IPerson {
name: string;
getAge: (age: number) => number;
}

class Person implements IPerson {
name = 'oxygen';

getAge = (age: number) => {
return age;
};
}

const person = new Person();
console.log(person.name); // oxygen

自动合并

interface的一个特点是可以使用相同的名称重复定义,相同名称最后会自动合并属性,这也是interfacetype上的一个关键区别

interface Person {
name: string;
}

interface Person {
age: number;
}

const person: Person = {
name: 'oxygen',
age: 20
}