一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
大家好,我是杨成功。
今天想探讨一个话题,就是 TypeScript 中的万能类型 any,我们到底该不该用?如果可以用,哪里可以用?如果不能用,哪里绝不能用?
我们知道 TypeScript 是一个类型检查器,为 javascript 装上了静态类型检查的翅膀,还带着它飞了好久。但是 TypeScript 有时候也给我们带来了不好麻烦,尤其是一些复杂的数据结构,本来是一个简单的获取数组下标,或者获取对象属性,TypeScript 总要给你丢一堆报错。
心态好的同学,找到定义变量的地方,再重新完善一下类型的定义,解决掉问题;心态不好的同学,他娘的我还有业务要写呢,光花时间在定义类型上了,于是一个 any 解决所有问题。
对于祭出 any 大法的同学,我要说,慎重啊!有些地方勉强行,有些地方是真不行,别再任性了!
哪些地方行
先想一下我们用 TypeScript 主要为了解决什么问题,其实很简单也很直接,就是怕你手瓢,莫名其妙变量名写错,或者数组对象操作不严谨,导致线上总报 ReferenceError
的错误。
如果你要组合数据。定义一个临时变量存放数组或对象,这个时候你可以定义 any。比如这样:
var fruits = ['苹果', '葡萄', '香蕉']
const TestArray = ()=> {
let arr: any[] = []
fruits.forEach(row=> {
arr.push({
value: row, label: row
})
})
}
你看这个时候,变量 arr
只是临时变量,如果要严格定义类型的话你非得写一个 interface 不可,不写的话又报错,所以这个地方可以用 any 类型。
除了临时变量,某些函数的参数也可以指定 any,比如一个转换格式的函数:
const ConvertData = (data: any, code: number = 200)=> {
return { code, data }
}
这个函数就很简单了,参数 data
可能是任意类型,所以直接丢一个 any 是可以的。但是一般通用的工具函数都是需要严格指定参数类型的,不可偷懒。
哪些真不行
如果涉及到全局共用的数据,就不能指定 any 了。这里要特别强调一百遍,接口返回的数据,类型不能用 any!不能用 any!不能用 any!
为啥这么激动?因为这个真的非常重要。其实我认为在我们正常的业务开发场景下,TypeScript 最大的用武之地就是对接口返回的数据(对象和数组)定义类型。因为除了页面排版外,我们绝大部分的工作都是在操作或者使用接口返回的数据。
如果接口返回的数据结构复杂,你在频繁使用的时候非常容易出错,比如某个字段少了一个字母,某个属性少了判空的逻辑,这都不可避免。
但是如果你严格定义了类型,那么我们在任意一个组件里使用这些数据,基本不会出现前面说的这种低级错误,因为 TypeScript 强大的类型提示已经帮你验证了可能的错误隐患。
但如果你非要指定 any
,那就芭比Q了。你是免去了定义繁琐的 interface,但 TypeScript 也会跟你闹脾气,不帮你检测类型了,那你还不是容易出错?
除此之外,如果你在写第三方开源库,或者公共函数,那也一定一定不要用 any,因为你的函数是要交给别人使用的,别人很可能传参错误,或者返回错误,这很常见。
如果你没有严格定义类型,用了好多 any,那么别人在使用的时候就得不到正确的传参提示,这样即便使用者书写错误 TypeScript 也无法判断,那么你的代码就不算合格。
总之,涉及到公共使用的代码,函数也好组件也好,一定要严格定义类型!
怎么优雅的定义类型
定义接口返回数据的类型,我一般会在存储数据文件的同级目录下,单独定义一个 types.ts
的文件。
比如我在某个目录下的 index.ts
文件中获取了接口数据:
import axios from 'axios'
import { DateType } from './types'
class OrderStore {
lists: DateType[] = []
fetch = async ()=> {
let res: any = await axiox.get('xxxx')
this.lists = res.data || []
}
}
那么 DateType
这个类型在 types.ts 文件中定义方式如下:
export interface DateType {
id: number
area_id: number
area_name: string
order_no: string
order_type: number;
products_name: string
sale_price: string
payable_amount: string
}
这个类型字端根据你接口返回的格式定义,有时候接口返回一大堆,你也不用全都定义在这里,需要用啥字段就定义啥,如果欠缺了后续在这里补充就行。
加我入群
本文来源公众号:程序员成功,这里主要分享前端工程与架构的技术知识。也可以加我微信 ruidoc
进工程与架构主群,与大佬们一同探索学习进步!