一、Interface基础
1、Interface是什么
interface Person {
name: string;
age: number;
}
上面的代码定义了一个Person接口,它包含了两个属性name和age,分别为字符串类型和数字类型。
2、Interface的作用
Interface可以用来对对象、函数、类等进行类型检查,同时也可以充当文档,让开发者清楚了解接口的使用方法和所期望的返回值类型。
3、Interface的继承
interface Person {
name: string;
age: number;
}
interface Student extends Person {
grade: number;
}
上面的代码定义了一个Student接口,它继承了Person接口,并且新增了一个grade属性,为数字类型。
二、Interface的可选属性和只读属性
1、可选属性
interface Person {
name: string;
age?: number;
}
const person1: Person = { name: 'Alice' };
const person2: Person = { name: 'Bob', age: 20 };
上面的代码中,age属性在Person接口中被定义为可选属性,意味着在对象实例化时可以选择不传入age属性。
2、只读属性
interface Person {
readonly name: string;
age: number;
}
const person: Person = { name: 'Alice', age: 20 };
person.name = 'Bob'; // 编译报错,无法更改只读属性
上面的代码中,name属性在Person接口中被定义为只读属性,意味着该属性无法被更改。
三、Interface的函数定义
1、函数类型
interface SearchFunc {
(source: string, subString: string): boolean;
}
const mySearch: SearchFunc = function (source: string, subString: string) {
return source.indexOf(subString) > -1;
};
上面的代码定义了一个函数类型的接口SearchFunc,并且将其赋值给mySearch变量,该变量是一个函数,接收两个字符串类型的参数,返回布尔类型的值。
2、可选参数和默认参数
interface BuildNameFunc {
(firstName: string, lastName?: string): string;
}
function getName(name: BuildNameFunc, firstName: string, lastName = 'Doe'): string {
return name(firstName, lastName);
};
const fullName = getName(function(firstName, lastName) {
return `${firstName} ${lastName}`;
}, 'John');
console.log(fullName); // John Doe
上面的代码中,BuildNameFunc接口包含两个参数,其中lastName是可选参数,可以不传入,同时也可以设置默认值。getName函数接收一个函数类型的参数name,并且调用该函数返回字符串类型的值。
四、Interface的类定义
1、类类型实现接口
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) {}
}
上面的代码中,定义了一个ClockInterface接口,包含了currentTime属性和setTime方法。Clock类实现了该接口,并且实现了currentTime属性的赋值和setTime方法的定义。
2、类类型接口
interface ClockConstructor {
new(h: number, m: number): ClockInterface;
}
interface ClockInterface {
tick(): void;
}
function createClock(ctor: ClockConstructor, h: number, m: number): ClockInterface {
return new ctor(h, m);
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
console.log("tick tock");
}
}
const digital = createClock(DigitalClock, 12, 17);
const analog = createClock(AnalogClock, 7, 32);
上面的代码中,定义了一个ClockConstructor接口,包含了new方法,该方法返回ClockInterface实例。createClock函数接收一个ClockConstructor类型的参数和两个数字类型的参数,返回一个ClockInterface实例。DigitalClock和AnalogClock类实现了ClockInterface接口,并且传递给createClock函数用于实例化。
五、Interface的其他使用场景
1、索引类型
interface StringArray {
[index: number]: string;
}
const arr: StringArray = ['Bob', 'Alice'];
const name: string = arr[0];
上面的代码中,定义了一个StringArray接口,表示字符串类型的数组,方括号内为索引类型,代表容器内元素的类型。
2、字符串字面量类型
interface Easing {
easeIn: string;
easeOut: string;
easeInOut: string;
}
const easing: Easing = {
easeIn: 'ease-in',
easeOut: 'ease-out',
easeInOut: 'ease-in-out'
};
上面的代码中,定义了一个Easing接口,为字符串字面量类型,代表了三种不同的easing动画类型。
3、混合类型
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
const counter = function (start: number) {} as Counter;
counter.interval = 123;
counter.reset = function() {};
return counter;
}
const myCounter = getCounter();
myCounter(10);
myCounter.reset();
myCounter.interval = 5.0;
上面的代码中,定义了一个Counter接口,是一个既可以像函数一样使用,又可以包含属性和方法的接口类型。
六、总结
通过本文的介绍,我们了解了TypeScript Interface在多种场景中的使用方式,从基本类型定义,到接口继承、可选属性和只读属性、函数类型定义、类类型实现接口、类类型接口、索引类型和混合类型,我们可以看到Interface的作用分布在TypeScript中的各个角落。