前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >typescript基础篇(3):接口

typescript基础篇(3):接口

作者头像
一粒小麦
发布2020-08-07 17:44:11
5440
发布2020-08-07 17:44:11
举报
文章被收录于专栏:一Li小麦

3. 接口

关于接口,你可以理解为定义了属性和类型,但是没有定义其它任何东西的构造函数。接口可以用来约束对象,函数乃至代码结构。

3.1 接口的使用

如果你和后端同事正在联调,讨论好的数据类型是这样的:

代码语言:javascript
复制
[{id:1,name:'djtao'},{id:2,name:'dangjingtao'}...]

试问,如何规范这样的一个接口呢?

代码语言:javascript
复制
interface List {
  id: number
  name: string
}

interface Result {
  data: List[]
}

const render = (result: Result) => {
  result.data.forEach((item) => {
    console.log(item)
  })
}

const result = {
  data: [{ id: 1, name: "djtao" }, { id: 2, name: "dangjingtao" }],
}

render(result)

这里我们使用接口来描述一个拥有id和name字段的List对象。并且定义Result是由List组成的数组。那么,一个标准的接口就被定义出来了。

3.2 接口数据处理

如果后端给你的数据加了一个age字段:

代码语言:javascript
复制
const result = {
  data: [{ id: 1, name: "djtao" }, { id: 2, name: "dangjingtao",age:31 }],
}

代码也不会报错。从这里体现了动态语言的特征(鸭子模型),只要满足接口的必要条件,就可以允许。

但是,如果:

代码语言:javascript
复制
render({
  data: [{ id: 1, name: "djtao" }, { id: 2, name: "dangjingtao", age: 31 }],
})

这样又会报错。

这时候就需要类型断言。断言时,render的入参用Result类型s规范。如下两种都是等价的:

代码语言:javascript
复制
// 在react(tsx)中使用容易被混淆
render(<Result>{
  data: [{ id: 1, name: "djtao" }, { id: 2, name: "dangjingtao", age: 31 }],
});

// tsx只能使用这种方式
render({
  data: [{ id: 1, name: "djtao" }, { id: 2, name: "dangjingtao", age: 31 }],
} as Result)

你也可以使用字符串索引签名,在定义List时:

代码语言:javascript
复制
interface List {
  id: number
  name: string
  [prop: string]: any // 允许接受其它属性
}

3.3 接口成员的特性

假设后端接口可能存在age属性,也可能不存在,前端需要根据此属性进行渲染——

代码语言:javascript
复制
interface List {
  id: number
  name: string
}

interface Result {
  data: List[]
}

const render = (result: Result) => {
  result.data.forEach((item) => {
    console.log(item)
    if (item.age) {// 报错
      console.log(item.age)
    }
  })
}

const result = {
  data: [{ id: 1, name: "djtao" }, { id: 2, name: "dangjingtao", age: 31 }],
}

render(result)

如果我给List定义了age,也不行(类型不兼容),这时候可以使用可选属性(加?)

代码语言:javascript
复制
interface List {
  id: number
  name: string
  age?: number
}

这样就符合预期了。

因为id是重要属性,还可以对id设置只读属性(readonly)

代码语言:javascript
复制
interface List {
  readonly id: number
  name: string
  age?: number
}

这时如果尝试修改id,就会报错。

上面的例子,属性个数都是确定的。如果是不确定的,可以使用索引属性

比如:

代码语言:javascript
复制
interface StringArray {
  [index: number]: string
}

let chars: StringArray = ["a", "b"]

表示声明了一个由字符串组成的数组。也可以混用:

代码语言:javascript
复制
interface StringArray {
  [index: number]: string
  [z: string]: string
}

3.4 用接口定义函数

回顾之前所学:在ts中定义一个函数可以是这样:

代码语言:javascript
复制
const add = (a: number, b: number) => a + b

用接口描述:一个函数,两个入参都是数字,返回的也是数字。

代码语言:javascript
复制
interface Add {
  (x: number, y: number): number
}
// 或者
type Add = (x: number, y: number) => number
let add: Add = (a, b) => a + b

type和interface 多数情况下有相同的功能,就是定义类型。但有一些小区别:type:不是创建新的类型,只是为一个给定的类型起一个名字。type还可以进行联合、交叉等操作,引用起来更简洁。interface:创建新的类型,接口之间还可以继承、声明合并。如果可能,建议优先使用 interface。

接口也可以同时用做返回函数/字符串和数字:

代码语言:javascript
复制
interface Lib {
  (): void
  version: string
  do(): void
}

// 这样实际上声明的是一个单例
// let lib: Lib = (() => {}) as Lib 

// 考虑工厂模式 可以创建多个实例
const getLib = () => {
  let lib: Lib = (() => {}) as Lib
  lib.version = "1.0"
  lib.do = () => {}
  return lib
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一Li小麦 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 3. 接口
    • 3.1 接口的使用
      • 3.2 接口数据处理
        • 3.3 接口成员的特性
          • 3.4 用接口定义函数
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档