# 接口

接口是对象的状态 (属性) 和行为 (方法) 的抽象 (描述),本质上是一种对对象的约束。例如我们要求一个对象必须要有 id 这个属性,且属性值必须为 number 。这在 javascript 上是做不到的,但在 typescript 中我们可以利用接口来实现。

// 需求:对象里必须要有 id 这个属性,且属性值为 number 类型
// 声明一个接口
interface IObj{ // 用 I 开头表示这是一个接口
	id:number
}
let obj1:IObj = {
    id:1, // ok
    name:'asuhe' //error 接口中未声明 name 属性
}
let obj2:IObj = {
    id:'a', //error 数据类型错误
}

# 可选属性 | 参数

在接口里约定的属性或参数都是必选的,若我们要求在接口中约定一些属性为可选属性那么只需要在后面加上 ?

// 需求:要求一个人的信息必须有名字,身高体重可选填
interface IPerson {
	name:string,
    height?:number,
    weight?:number
}
let obj:IPerson = {
	name:'asuhe' // ok
}

# 只读属性 | 参数

若我们想对象里某个参数只能读取不能修改,那么仅需在前面加上 readonly

// 需求:货物编号只能读取不能修改
interface IGoods {
	readonly id:number,
    name:string,
    weight?:number
}
let obj:IGoods = {
    id:1,
    name:'asuhe'
}
console.log(obj.id);
obj.id = 1 //error 不能赋值,只读属性

# readonly vs const

最简单判断该用 readonly 还是 const 的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用 const ,若做为属性则使用 readonly

# 函数类型

接口能够描述 JavaScript 中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述函数类型。

为了使用接口表示函数类型,我们需要给接口定义一个调用签名。它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。

/* 
接口可以描述函数类型 (参数的类型与返回的类型)
*/
interface ISum {
  (a:number,b:number):number
}
let sum:ISum = function(x:number,y:number):number{
    return x + y
}
console.log(sum(1,2)) // 3

# 类中使用接口

与 C# 或 Java 里接口的基本作用一样,TypeScript 也能够用它来明确的强制一个类去符合某种契约。

/* 
  类类型:实现接口
  1. 一个类可以实现多个接口
  2. 一个接口可以继承多个接口
  */
  interface IPerson {
    name: string,
    age: number
  }
  interface IStudent {
    course: string[]
  }
  // 类实现接口
  class Person implements IPerson {
    name: string
    age: number
    constructor(name: string, age: number) {
      this.name = name,
        this.age = age
    }
  }
  // 一个类实现多个接口
  class Student implements IPerson, IStudent {
    name: string
    age: number
    course: string[]
    constructor(name: string, age: number, course: string[]) {
      this.name = name
      this.age = age
      this.course = Array.from(course)
    }
  }
  // 一个接口继承多个接口
  interface IStudentAndPerson extends IPerson,IStudent{
    
  }