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

相关推荐
炫饭第一名13 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
进击的尘埃14 小时前
Vue3 响应式原理:从 Proxy 到依赖收集,手撸一个迷你 reactivity
javascript
willow14 小时前
JavaScript数据类型整理1
javascript
LeeYaMaster14 小时前
20个例子掌握RxJS——第十一章实现 WebSocket 消息节流
javascript·angular.js
UIUV15 小时前
RAG技术学习笔记(含实操解析)
javascript·langchain·llm
颜酱17 小时前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
FansUnion17 小时前
我如何用 Next.js + Supabase + Cloudflare R2 搭建壁纸销售平台——月成本接近 $0
javascript
左夕18 小时前
分不清apply,bind,call?看这篇文章就够了
前端·javascript
滕青山19 小时前
文本行过滤/筛选 在线工具核心JS实现
前端·javascript·vue.js
时光不负努力19 小时前
编程常用模式集合
前端·javascript·typescript