用于描述对象的类型。接口一般首字母大写,最好以大写字母I开头

可选的属性

如果存在不希望完全匹配接口中定义的属性,可以使用此特性(属性名?:类型),但是不允许添加未定义的属性

  1. interface SquareConfig {
  2. color?: string;
  3. width?: number;
  4. }

只读属性

希望对象中的有些字段只有在创建的时候被赋值,不能修改。可以使用(readonly 属性名:类型)

  1. interface Point {
  2. readonly x: number;
  3. readonly y: number;
  4. }
  5. let ro: ReadonlyArray<number> = a; // 使用ReadonlyArray创建不可修改的数组

注意:只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候:

额外的属性检查

  1. // 额外的类型检查
  2. interface SquareConfig {
  3. color?: string;
  4. width?: number;
  5. [propName: string]: any;
  6. }
  7. function createSquare(config: SquareConfig): { color: string; area: number } {
  8. return {
  9. color: "",
  10. area: 0,
  11. };
  12. }
  13. let squareOptions = { colour: "red", width: 100 }; // what? 为什么没有报错
  14. let mySquare = createSquare(squareOptions);
  15. //因为squareOptions不会经过额外属性检查,所以编译器不会报错
  16. //上面的方法只在squareOptions和SquareConfig之间有共同的属性时才好用。 在这个例子中,这个属性为width。如果变量间不存在共同的对象属性将会报错

函数类型

函数的参数名不需要与接口里定义的名字相匹配,要求对应位置上的参数类型是兼容的
函数的返回值类型是通过其返回值推断出来的,需要与接口定义相同

  1. interface SearchFunc {
  2. (source: string, subString: string): boolean;
  3. }
  4. let mySearch: SearchFunc;
  5. mySearch = function(src, sub) { // TypeScript 的类型系统会推断出参数类型
  6. let result = src.search(sub);
  7. return result > -1;
  8. };

可索引的类型

  • 定义索引的类型和索引的返回值的类型
  • 字符串索引和数字索引类型
  • 只读的索引签名

可以描述那些能够“通过索引得到”的类型,比如arr[10],map[‘map1’],描述了对象索引的类型和相应索引返回值的类型

  1. interface StringArray {
  2. [index: number]: string;
  3. }
  4. let myArray: StringArray;
  5. myArray = ["Bob", "Fred"];
  6. let myStr: string = myArray[0];

Typescript 支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用number来索引时,JavaScript 会将它转换成string然后再去索引对象。 也就是说用100(一个number)去索引等同于使用”100”(一个string)去索引,因此两者需要保持一致

  1. class Animal {
  2. name: string;
  3. }
  4. class Dog extends Animal {
  5. breed: string;
  6. }
  7. // 错误:使用数值型的字符串索引,有时会得到完全不同的Animal!
  8. interface NotOkay {
  9. [x: number]: Animal;
  10. [x: string]: Dog;
  11. }

字符串索引签名能够很好的描述dictionary模式,并且它们也会确保所有属性与其返回值类型相匹配

  1. interface NumberDictionary {
  2. [index: string]: number;
  3. length: number; // 可以,length是number类型
  4. name: string; // 错误,`name`的类型与索引类型返回值的类型不匹配
  5. }

最后,你可以将索引签名设置为只读,这样就防止了给索引赋值

  1. interface ReadonlyStringArray {
  2. readonly [index: number]: string;
  3. }
  4. let myArray: ReadonlyStringArray = ["Alice", "Bob"];
  5. myArray[2] = "Mallory"; // error!

任意属性

如果存在希望接口允许有任意的属性,可以使用此特性([x: string]:类型),一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集
一个接口中只能定义一个任意属性

  1. interface Person {
  2. name: string;
  3. age?: number;
  4. [propName: string]: any;
  5. }
  6. let tom: Person = {
  7. name: 'Tom',
  8. gender: 'male'
  9. };

类类型

接口描述了类的公共部分,而不是公共和私有两部分。

类静态部分与实例部分的区分

当一个类实现了一个接口时,只对其实例部分进行类型检查。 constructor 存在于类的静态部分,不在检查的范围内。
可以使用类表达式来定义类

  1. interface ClockConstructor {
  2. new (hour: number, minute: number);
  3. }
  4. interface ClockInterface {
  5. tick();
  6. }
  7. const Clock: ClockConstructor = class Clock implements ClockInterface {
  8. constructor(h: number, m: number) {}
  9. tick() {
  10. console.log("beep beep");
  11. }
  12. };

继承接口

  1. interface Square extends Shape, PenStroke{}

混合类型

接口继承类

当接口继承了一个类类型时,它会继承类的成员但不包括其实现,接口同样会继承到类的 private 和 protected 成员。这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)