是时候终结关于ts中type和interface之争了

typeinterface之争其实很简单。

比如有如下函数定义:

typescript 复制代码
function fn (props: Props) {}

适合使用interface的场景

如果这个props只需要满足几个条件即可,比如只要是任意包含name字段的Object都行,例如:

typescript 复制代码
interface Props {
  name: string
}

function fn (props: Props): string {
  return 'hello ' + props.name
}

type Human = {
  name: string,
  age: number
}

interface Dog {
  name: string,
  color: string
}

const h1: Human = { name: '张三', age: 18 }
const d1: Dog = { name: '大黄', color: 'yellow' }

console.log(fn(h1))
console.log(fn(d1))

此时fn参数不管是,typeHuman,还是interfaceDog,只要包含了name字段都可以。

适合使用type的场景

还是用刚才fn函数举例子,如果props要求传入的参数必须满足全部的条件,即必须是指定的类型,例如:

typescript 复制代码
type Props = {
  name: string,
  age: number
}

function fn (props: Props): string {
  return 'hello ' + props.name
}

console.log(fn({ name: '张三', age: 18 }))

const p1: Props = { name: '李四', age: 20 }
console.log(fn(p1))

此时只要传入的参数不符合Props定义的任何字面和非字面Object都会报错,比如非字面量报错:

typescript 复制代码
/**
 * 报错:
 * 类型"{ name: string; }"的参数不能赋给类型"Props"的参数。  
 * 类型 "{ name: string; }" 中缺少属性 "age",但类型 "Props" 中需要该属性。ts(2345)
 * [test.ts(3, 3): ]()在此处声明了 "age"。
 */
console.log(fn({ name: '张三' }))

字面量报错:

typescript 复制代码
/**
 * 类型"Dog"的参数不能赋给类型"Props"的参数。
 * 类型 "Dog" 中缺少属性 "age",但类型 "Props" 中需要该属性。ts(2345)
 * test.ts(3, 3): 在此处声明了 "age"。
 * const dog: Dog
 */
interface Dog {
  name: string,
  color: string
}
const dog: Dog = { name: '大黄', color: 'yellow' }
console.log(fn(dog))

typescript对我的意义

在我看来,ts的出现解决的最大痛点是js在开发维护的过程中,降低重构的心智负担,项目越来越大之后,有的复杂function时间一久,你自己都忘了怎么用了,只能去全局搜索相关用例。

如果要重构修改的话,就更头疼了,保不齐改漏了什么地方,测试又没覆盖到,bug就这样出现了,有bugbug这倒也不是啥大事,主要是重构和修改的过程中心智负担很大,生怕漏了什么。

js项目中,如果你写了一个底层库,以往的团队合作,别人要使用你的库,或者你要使用别人的库,只能是:写文档看文档、写jsdoc、自己看代码实现、自己看代码用例,不管是哪个场景都有不小的心智负担,而有了ts的话,不敢说完美解决,但至少能在一些场景下减轻不少心智负担。比如一个有着复杂参数函数的传参,基于vscode的代码提示,能很清晰的知道参数该怎么传,返回值是啥,等等。

typescript与jsdoc

jsdoc确实可以定义类型,但比起ts还是要繁琐不少,并且没有足够强制性的约束力,ts在编译时可以检查报错,不过jsdoc也是有一些应用场景的,比如仅需要少了定义描述介入的时候,对老项目的补充维护之类的。还是那句话,对待任何技术,永远不要二极管,得根据具体场景做选择才是最合理的。

结论

type是要求必须是该type字面定义满足该type定义,interface任意字面定义非字面定义满足该interface定义即可。

其实真正接触过面向对象思想的人(仅学过的不算),都能理解typeinterface的区别和何时该用哪个。

当初我初学的时候也不理解,既然有各种class定义了,为何还需要interface,觉得interface啥都不做,就在哪里定义一下,显得很多余,后来接触了Android开发后,发现有的函数方法,可以接受的参数只要满足某一个interface的定义就可以传入,极大的方便了开发,降低设计成本。

也可以说是存在即可合理吧,按需按场景决定用哪个,之前看过有帖子说无脑梭其中一个就行了,我觉得太二极管了,这不应该是程序员该有的思维,还是应该结合多方面因素综合考虑哪个更合适更好一些。

还有一些人觉得,这是把java那一套丑思想给硬搬过来套在js上了,对于这类人,我只能说尊重祝福,希望你永远不会有需要typescript的时候。

相关推荐
渴望成为python大神的前端小菜鸟几秒前
JS宏任务 & 微任务 API 速查表
javascript
前端小王呀3 分钟前
自定义图表相关配置
android·前端·javascript
chilavert3188 分钟前
技术演进中的开发沉思-226 Ajax:前端兼容
javascript·架构
西西学代码8 分钟前
flutter---进度条
前端·javascript·flutter
时间的情敌24 分钟前
Vue3 和 Vue2 的核心区别
前端·javascript·vue.js
Aevget29 分钟前
DevExtreme JS & ASP.NET Core v25.2新功能预览 - 提升AI扩展功能
javascript·人工智能·ui·asp.net·界面控件·devextreme
春卷同学30 分钟前
电子蛇对战 - Electron for 鸿蒙PC项目实战案例
javascript·electron·harmonyos
1024小神36 分钟前
android studio最新版在toolbar工具栏显示back和forward按钮
javascript·html·android studio
悟能不能悟36 分钟前
vue项目,url访问不了,用route-link跳过去就可以访问,为什么
前端·javascript·vue.js
程序媛_MISS_zhang_011037 分钟前
APP中列表到详情,详情返回列表时候,返回定位到之前查看详情那条数据
前端·javascript·vue.js