likes
comments
collection
share

先别急着喷,我们继续聊interface/type在ts中定义类型的问题接上一篇 “为什么在TypeScript上不使用

作者站长头像
站长
· 阅读数 22

先别急着喷,我们继续聊interface/type在ts中定义类型的问题接上一篇 “为什么在TypeScript上不使用

为了方便,我们接下来用 它俩 来指代 interface以及type

一、类可以扩展行为,而它俩不能

举个例子,是用户就会有姓名,是用户就会吃饭。

1. 使用 interface

那么先声明这个结构,interface声明方法还是可以的,不过那是个抽象方法,需要其他地方来实现:

interface IUser {
  name: string
  eat(): void
}

const user: IUser = {
  name: 'Hamm',
  eat(): void {
    console.log(`${this.name}吃饱了`)
  },
}
console.log(user)

没有办法,要想赋值成功,就必须给右侧的 Object 注入一个 interface 要求实现的方法 eat,使用的时候才去声明,多少是有些草率的。先看看打印结果:

先别急着喷,我们继续聊interface/type在ts中定义类型的问题接上一篇 “为什么在TypeScript上不使用

好家伙,打印成这个鬼样子,我开始怀疑 Object.keys 会不会打印出 eat ?

先别急着喷,我们继续聊interface/type在ts中定义类型的问题接上一篇 “为什么在TypeScript上不使用

不出所料。那么可能造成什么问题,就留给看官们去思考啦。

2. 使用 type

Type 在这个场景下吧,跟 interface 没啥大区别了。

type User = {
  name: string
  eat(): void
}

const user: User = {
  name: 'Hamm',
  eat(): void {
    console.log(`${this.name}吃饱了`)
  },
}
console.log(user)
console.log(Object.keys(user))

那就不多说了。

3. 使用 class

使用 class 来定义的话,那就很简单也很标准的操作了:

class User {
  name!: string

  eat() {
    console.log(`${this.name} eating...`)
  }
}

const user = new User()
user.name = 'Hamm'
user.eat()
console.log(user)
console.log(Object.keys(user))

打印出来瞧瞧呗?

先别急着喷,我们继续聊interface/type在ts中定义类型的问题接上一篇 “为什么在TypeScript上不使用

可以看到这几个优势:

  • 控制台打印时具名输出了数据的所属类型(红色箭头)
  • 行为方法被挂载到了原型链上(如绿色箭头)
  • Object.keys 不会遍历到行为

二、类可以继承行为,而它俩不能

前面已经说过了,它俩只能定义结构,而对于行为它俩就有点难过了。

而定义行为恰好是编码阶段非常重要的事情,比如公共方法的实现:

定义一个基础API,支持CURD

class BaseApi{
    get(){
    }
    
    delete(){
    }
    
    getPage(){
    }
    
    // 等等等等
}

再定义业务API,就无需再实现一遍了

class UserApi extends BaseApi {
    login(){
    }
    
    register(){
    }
}

这不是美滋滋?

三、类可以用行为来留余地,而它俩不能

举个例子:

后端:“如果用户状态为 1 的时候,不允许编辑用户的信息” 前端:“只有1的时候不允许编辑吗?” 后端:“目前的产品需求是。”

记住这个 “目前”,要考。

不管是用 class/interface/type 都可以这么写。

<button :disabled="user.status === 1">编辑</button>

不过,后端说只是目前,这里就写死了,不太方便扩展了,如果这个按钮出现的地方很多的话。

如果是用它俩,那就得在其他地方写一个行为控制的方法了。

如果用的是 class,那就简单了。

class User {
    status!: number
    
    ediable(){
        // 下次其他状态也不允许编辑的时候,直接改这里的状态码
        return [1].includes(this.status)
    }
}

上面直接扩展了一个 editable 行为,把规则也写活了,使用的地方直接使用即可。即使要改,也只改这个行为方法内部的代码即可。

<button :disabled="!user.editable()">编辑</button>

四、写完总结就收工

至于 interface type 的优势吧,本文就不聊了,他们的优势我们也是有使用的 :)

但对于业务数据类型的定义,我们依然是选择了 class,利用了它的优势,因为产品设计的变更的一些问题能得到更好的处理。

而在 装饰器参数中,我们也使用了 interface 作为类型定义的方式,毕竟这玩意是自己写的,不会因为第二方的原因变动。至于 type,我们的项目的确没什么使用场景。

相关前端面向对象开发的源代码可以参考:

Github: github.com/HammCn/AirP…

Gitee: gitee.com/air-power/A…

如对你有帮助,感谢点赞收藏和分享,也感谢点Star的各位。

这一篇应该是 《用TypeScript写前端》 这个专栏的最后一篇了,之后应该不会再继续这个系列的文章了。欢迎各位继续关注后续的其他专栏,可能是偏网络和运维的,也可能是偏后端的,也有可能是偏架构的。

就这样~

转载自:https://juejin.cn/post/7374239278052605987
评论
请登录