TypeScript:为什么不要用any声明类型

2,085 阅读5分钟

不知道你是否经历过后端返回的某个值,因为你的手抖导致写错一个字母,后面测BUG的时候反复看代码都找不到问题所在,经过好几个小时的反复查看,结果发现是因为你取后端返回值的时候,写错一个字母导致的。

虽然我没有经历过这种情况,但是我看身边写JavaScript的那些同事几乎都犯过这样的问题,那么如何避免这种问题呢?没错,TypeScript是你的不二选择。

由于现在前端对于TypeScript掌握的程度不同,所以大部分人在编写TypeScript项目时,都会毫无节制的使用any,无论是因为实在不知道如何声明对应的类型,还是因为嫌麻烦而使用any,都会失去TypeScript的许多特点。

还有甚者,编辑器已经给出警告甚至错误提示了,但是只要代码能够跑起来,他都不会去理会这些错误提示。

因为TypeScript独有的一些东西,比如类型声明,即使你代码写的再多,都不会编译进最终的js文件,所以即使TypeScript类型报错,但是代码依然能够进行编译并且运行。

1. TS实例

众所周知,后端返回的数据中,可能有一部分属性会在一定的情况下返回null,如果你不对null进行一些处理,那么你的代码很可能就会发生报错,导致页面崩溃,比如下面的这种情况:

 export const obj: any = {};

 // 执行下面这段代码时就会报错
 console.log(obj.info.name); 

由于你使用了any进行声明,那么编辑器不会有任何提示:

image-20220314102536985

你也可以手动进行下面的处理:

 export const obj: any = {};

 // 不会再报错,会输出 undefined
 console.log(obj && obj.info && obj.info.name);

在TypeScript中,上面的代码可以简写为(ES11也支持了这种写法):

 export const obj: any = {};

 // 不会再报错,会输出 undefined
 console.log(obj?.info?.name);

但是!在大多数情况下,你可能都不会注意到后端传回来的这些数据可能为空,那么哪些时候你需要使用?.进行处理,哪些时候数据不会为空,你不需要用?.进行处理。

如果你在所有地方都打上?.那么也没错,这样至少保证代码不会因为取不到值而报错,但这就严重不符合自己的代码书写习惯,写起来会很别扭。

而上面的代码通过TypeScript正确声明类型来进行编写会是什么样的情况呢?其实编辑器会给你一个错误提示:

image-20220314102655382

这里说一下Obj这个接口的类型声明,info?:后面这个?:代表后面的参数可以不存在,即为undefined,而!:代表后面的参数一定会存在,我个人几乎不使用!:

如果你像上面这样正确的声明了类型,那么这里会有一个错误提示,编辑器会告诉你info可能为undefined,你的代码如果不进行处理,那么就有可能会发生报错导致页面崩溃情况。

这个时候你只需要加上?.这个错误提示就会消失:

image-20220314102731974

需要值得注意的是,接口返回的数据类型,如果你不声明的话统统都是any,在下面,会说一下如何声明接口的响应参数类型。

2. TS实力

上面的情况其实在自己编写代码的过程中遇到undefined的情况还是比较少,因为自己写代码的时候一般会给一些默认值。

前不久一个后端问我,当数据库中没有查询到数据的时候,我是应该直接返回一个null值还是手动处理一下返回一个空的数组,例如下面这两种情况:

 {
   "data": null
 }

 {
   "data": []
 }

我说:我觉得就像后端应该对于前端实行零信任原则一样,前端对于后端的数据也需要实行零信任原则,因为后端可能在查数据库时没有查找到对应的数据的时候都会返回null值,而前端如果没有处理这个值,默认后端返回的数据为空数组,而使用了map或者forEach进行遍历,那么就会造成页面崩溃。

由于返回数据类型是声明的any,所以不会得到任何提示,比如下面的模拟代码:

 export let data: any = {};

 data.data.forEach((data) => {});

image-20220314112023174

而如果使用了正确的类型声明,那么编辑器会给你一个报错提示:

image-20220314112118873

这个时候你只需要使用?.处理一下,这个报错提示就会消失:

image-20220314112151244

所以接口类型声明其实是一件非常重要的事情,不推荐使用any进行声明。

3. axios

axios是在公司里目前用的非常多的一个XMLHttpRequest请求库。

image-20220314105915438

axios提供了泛型,用来声明响应参数类型,如果你不使用泛型声明响应参数类型,那么axios返回的参数类型就是any,如上图所示。

所以推荐你还是使用泛型声明一下响应参数的类型,以得到正确的TypeScript提示:

image-20220314110044430

和上面一样,只需要你使用?.处理一下,那么这个报错提示就不再存在:

image-20220314110214554

4. fetch

现代浏览器已经支持了Fetch API,使用Fetch API你不需要额外的引入第三方库,比如axios,你也能得到和axios差不多的体验。

关于这个API我也写了一篇对应的总结文章:越来越火的网络请求Fetch和Axios到底有什么区别

看下面的代码,如果你没有声明返回类型的话,默认声明也同样是any

image-20220314105548562

和axios一样如果你给予了返回类型,那么编辑器同样会提示你某个属性可能为undefined,让你进行处理:

image-20220314105707910

5. 最后

如果你在TypeScript项目中少用或者不用any,那么编辑器提示带来的收益是非常多的,而根据这些代码提示去规范你的代码,我个人感觉可以减少项目80%的潜在BUG。