是时候终结关于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的时候。

相关推荐
yuezhilangniao7 小时前
AI智能体全栈开发工程化规范 备忘 ~ fastAPI+Next.js
javascript·人工智能·fastapi
铅笔侠_小龙虾8 小时前
Flutter Demo
开发语言·javascript·flutter
2501_944525548 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 账户详情页面
android·java·开发语言·前端·javascript·flutter
wangdaoyin20108 小时前
若依vue2前后端分离集成flowable
开发语言·前端·javascript
天天进步20159 小时前
AI Agent 与流式处理:Motia 在生成式 AI 时代的后端范式
javascript
心柠9 小时前
vue3相关知识总结
前端·javascript·vue.js
常年游走在bug的边缘10 小时前
掌握JavaScript作用域:从函数作用域到块级作用域的演进与实践
开发语言·前端·javascript
极致♀雨10 小时前
vue2+elementUI table表格勾选行冻结/置顶
前端·javascript·vue.js·elementui
林shir10 小时前
3-15-前端Web实战(Vue工程化+ElementPlus)
前端·javascript·vue.js
换日线°12 小时前
前端炫酷展开效果
前端·javascript·vue