ts中使用 interface 关键字定义一个接口, 接口用来定义对象类型或者函数类型,类类型等等, 并且可以设置属性只读, 属性可选等操作, 总而言之 interface 的功能很强大 . 接下来玩一玩 .

要点概览 :

pointexplain
普通接口属性必须完全定义,可改
只读属性对象中属性只读不能修改
可选属性属性不是必须定义的
函数类型接口还能定义函数类型
索引类型未知数量的属性
类类型约束类
继承接口继承于另一个接口
混合类型定义函数并拥有对象的属性
接口继承类接口继承类可供类实现或定义对象


1. 定义一个普通接口

  • 完整定义, 可以修改

接口使用 interface 关键字进行定义, 在没有设置特殊标识时, 使用接口作为类型定义变量必须将接口内的属性完整定义, 不然就会报错 .  接口定义对象默认属性是可以更改的

interface Person {
  name: string
  age: number
}
const o: Person = {
  name: 'a',
  age: 1
}
o.age = 2
console.log(o) // {name: 'a', age: 2}

2. 定义只读属性的接口

  • 关键字 readonly 
  • 完整定义, 不能修改

用 readonly 修饰的属性不能进行修改

interface Person {
  name: string
  readonly age: number
}
const o: Person = {
  name: 'a',
  age: 1,
}
// o.age = 2 // 无法分配到 "age" ,因为它是只读属性。
console.log(o)

3. 定义属性可选的接口

  • 关键字  ?
  • 根据是否可选进行定义, 可以修改

属性名后加 ? 号, 属性可传可不传

interface Person {
  name?: string
  readonly age: number
}
const o: Person = {
  age: 1,
}
console.log(o) // { age: 1}

4. 索引类型签名

当不确定对象中有哪些属性, 推荐使用索引类型签名 . 简单一点来说, 大概就是定义了对象中键值的类型, 允许定义任意多的键值对

interface index {
  [key: string]: string
}
// type index = {
//   [key: string]: string
// }
// 对象中的键最终都是字符串类型的
const obj: index = {
  1: '1',
  2: '1',
  3: '1',
}

数组的定义同样也可以使用索引类型签名 . 

限制了数组的键和值的类型, 数组的键本来就是数字类型的, 因此可以忽略掉, 只关注值类型即可, 但是你绝对不能将 key 的类型设置成 string, 自相矛盾了...

// 数组类型签名 好像没什么软用 感觉和 string[]一样
interface arr {
  [key: number]: string
}
const arr1: arr = ['0', '1']
console.log(arr1[0])  // 0
console.log(arr1['1'])  // 1

5. 类类型

如果想对类中的内容进行约束, 那么考虑类类型, 定义一个接口, 使用 implements 关键字实现接口

interface Dog {
  name: string
  wang?(str?: string): string
}

// 类实现一个接口通过关键字 implements
class D1 implements Dog {
  name: string
  wangstr: string
  wang(str: string) {
    return str
  }
  constructor(name: string, wangstr: string) {
    this.name = name
    this.wangstr = wangstr
  }
}

const demo = new D1('hei', 'shagou')
console.log(demo.name)
console.log(demo.wang('1'))

6. 继承接口

接口可以继承于另一个接口, 使用它的属性及类型 , 但是不可以相互继承, 这会引起不必要的错误

interface Animal {
  kind: string
}

interface Dog extends Animal {
  name: string
}

const dog: Dog = {
  name: 'hei',
  kind: 'dog',
}

7. 混合类型

可以定义函数, 也可以拥有对象的属性

interface Fn {
  (start: number): string
  interval: number
  reset(): void
}

function createFn(): Fn {
  let fn = <Fn>function fn(start: number) {
    return start + ''
  }
  fn.interval = 1
  fn.reset = () => {}
  return fn
}

const fn1 = createFn()
console.log(fn1) // [Function: fn] { interval: 1, reset: [Function (anonymous)] }

8. 接口继承类

接口通过 extends 可以继承一个类的所有成员, 包括类中的private和protected成员, 我们可以用类实现这个接口或者用这个接口定义对象都是可行的, 只需要注意成员的公共和私有即可

  •  public 允许在类的实例访问父类的属性

  • protected 允许继承于父类的子类中访问父类的属性

  • private 不允许类实例和子类继承中访问父类的属性

class Control {
  public state: any
}

interface SelectableControl extends Control {
  select(): void
}

class Button implements SelectableControl {
  state = 1
  select() {}
}
const b = new Button()
console.log(b.state)

const obj: SelectableControl = {
  state: 1,
  select() {},
}
console.log(obj)

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐