您的位置:

TypeScript Interface的使用详解

一、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中的各个角落。