给团队做次TypeScript分享(三)—— 接口(interface) 和 type

478 阅读3分钟

接口(interface)

接口可以用来描述一个具体的对象、描述函数类型或者描述类的类型

  • 描述一个具体的对象

    interface IOption {
      label: string;
      value: number;
    }
    
    let obj: IOption = {
      label: "key",
      value: 1,
    };
    
  • 描述函数类型

    interface userInfoFunc {
      ( age: number, name: string ) : string
    }
    
    let exampleFuncOne: userInfoFunc = function (age: number, name: string) {
      return `${name}今年${age}岁了`
    }
    
    let exampleFuncTwo: userInfoFunc = (year: number, monicker: string) => {
      return `${monicker}今年${year}岁了`
    }
    
  • 描述类类型,使用 implements 实现接口

    interface IAnimal {
      name: string;
      age: number;
    }
    
    class Panda implements IAnimal {
      name = "mike";
      age = 18;
    }
    
  • 描述构造函数

    interface People {
      run: () => void;
    }
    
    interface PeopleConstructor {
      new (name: string): People;
    }
    
    class Student implements People {
      constructor(name: string) {}
      run() {
        console.log("run");
      }
    }
    
    function createPeople(construction: PeopleConstructor, name: string): People {
      return new construction(name);
    }
    
    let stu = createPeople(Student, "小明");
    

接口的属性

  • 可选属性

    在可选属性名字定义的后面加一个?符号,表示该属性“可有可无”

    interface IOption {
      label?: string;
      value: number;
    }
    
    let obj: IOption = {
      value: 1,
    };
    
  • 只读属性

    在只读属性名字定义的前面加上关键词 readonly,表示该属性赋值后不可再改变

    interface IUser {
      readonly name: string
      readonly age: number
    }
    let myUser: IUser = {
      name: 'mike',
      age: 18
    }
    myUser.age = 20 // error
    

可索引的类型

可索引类型具有一个 索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。

interface StringArray {
  [index: number]: string;
}
let nameArray:StringArray = ['mike', 'jack'] // ok
let numArray:StringArray = [1,2] // error

如上:StringArray的索引签名表示,当使用 number类型 索引时会得到 string类型

Typescript 支持 number 和 string 两种索引签名

两种可以同时使用,但是,由于使用 number 索引时,js 默认会将其转化为 string 再去索引对象,比如 100 (number)的索引等同于使用 ”100“ (string)去索引。

let obj = {
  100 : 'digital'
}
console.log(obj[100] === obj["100"]) // true

所以,数字索引的返回值必须是字符串索引返回值类型的子类型。

class Animal {
    name: string;
}
class Dog extends Animal {
    breed: string;
}

interface NotOkay {
    [x: number]: Animal;
    [x: string]: Dog;
} // error

interface Okay {
    [x: number]: Dog;
    [x: string]: Animal;
} // ok

字符串的索引签名会让所有属性与其返回值类型相匹配。

interface StringIndexSign {
  quantity: 20; // error
  visible: true; // error
  name: 'jack'; // ok
  10: 0; // error
  11: ''; // ok
  [x: string]: string;
}

接口继承

和类一样,接口也可以相互继承。

interface People {
  name: string;
}

interface China extends People {
  language: string
}

interface Usa extends People {
  skinColor: string
}

interface HalfBlood extends China, Usa{ // 也可以继承多个
  weight: number
}

let Jessie:HalfBlood = {
  name: 'Jessie',
  language: 'Chinese',
  skinColor: 'yellow',
  weight: 50,
}

接口声明合并

同名的接口会把各自的成员合并到一起

interface people {
  name: string
}
interface people {
  age: number
}  

const p1: people = {
  name: 'mike',
  age:18
}

如果两个接口中同时声明了同名的非函数成员且它们的类型不同,则编译器会报错。

interface people {
  height: string
}
interface people {
  height: number // error
}

对于函数成员,每个同名函数声明都会被当成这个函数的一个重载。

类型别名 type

可以借助 type 给类型起一个新名字。这里 type 只是创建一个新名字来引用那个类型,并不会新建一个类型。

type myString = string
let userName: myString = ''

type stringOrNumber = string | number
let myVariable = 1

interface people {
  name: string
}
type myPeople = people

interface 和 type

interface 和 type 可以描述一个对象或者函数,

type 可以声明基本类型别名,联合类型,元组等类型等等,interface不行

interface 支持声明合并,可以被 extends 和 implements,type 不支持