是时候终结关于ts中type和interface之争了
type
和interface
之争其实很简单。
比如有如下函数定义:
function fn (props: Props) {}
适合使用interface
的场景
如果这个props
只需要满足几个条件即可,比如只要是任意包含name
字段的Object
都行,例如:
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参数不管是,type
的Human
,还是interface
的Dog
,只要包含了name
字段都可以。
适合使用type的场景
还是用刚才fn函数举例子,如果props
要求传入的参数必须满足全部的条件,即必须是指定的类型,例如:
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
都会报错,比如非字面量报错:
/**
* 报错:
* 类型“{ name: string; }”的参数不能赋给类型“Props”的参数。
* 类型 "{ name: string; }" 中缺少属性 "age",但类型 "Props" 中需要该属性。ts(2345)
* [test.ts(3, 3): ]()在此处声明了 "age"。
*/
console.log(fn({ name: '张三' }))
字面量报错:
/**
* 类型“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
就这样出现了,有bug
修bug
这倒也不是啥大事,主要是重构和修改的过程中心智负担很大,生怕漏了什么。
在js
项目中,如果你写了一个底层库,以往的团队合作,别人要使用你的库,或者你要使用别人的库,只能是:写文档看文档、写jsdoc
、自己看代码实现、自己看代码用例,不管是哪个场景都有不小的心智负担,而有了ts的话,不敢说完美解决,但至少能在一些场景下减轻不少心智负担。比如一个有着复杂参数函数的传参,基于vscode
的代码提示,能很清晰的知道参数该怎么传,返回值是啥,等等。
typescript与jsdoc
jsdoc
确实可以定义类型,但比起ts
还是要繁琐不少,并且没有足够强制性的约束力,ts
在编译时可以检查报错,不过jsdoc
也是有一些应用场景的,比如仅需要少了定义描述介入的时候,对老项目的补充维护之类的。还是那句话,对待任何技术,永远不要二极管,得根据具体场景做选择才是最合理的。
结论
type
是要求必须是该type
或字面定义
满足该type
定义,interface
是任意字面定义
或非字面定义
满足该interface
定义即可。
其实真正接触过面向对象思想的人(仅学过的不算),都能理解type
和interface
的区别和何时该用哪个。
当初我初学的时候也不理解,既然有各种class
定义了,为何还需要interface
,觉得interface
啥都不做,就在哪里定义一下,显得很多余,后来接触了Android
开发后,发现有的函数方法,可以接受的参数只要满足某一个interface
的定义就可以传入,极大的方便了开发,降低设计成本。
也可以说是存在即可合理吧,按需按场景决定用哪个,之前看过有帖子说无脑梭其中一个就行了,我觉得太二极管了,这不应该是程序员该有的思维,还是应该结合多方面因素综合考虑哪个更合适更好一些。
还有一些人觉得,这是把java那一套丑思想给硬搬过来套在js上了,对于这类人,我只能说尊重祝福,希望你永远不会有需要typescript的时候。
转载自:https://juejin.cn/post/7350466998314975266