一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情。
本文的翻译于<<Effective TypeScript>>, 特别感谢!! ps: 本文会用简洁, 易懂的语言描述原书的所有要点. 如果能看懂这文章,将节省许多阅读时间. 如果看不懂,务必给我留言, 我回去修改.
技巧44:跟踪你的类型覆盖率来防止类型安全的倒退
当你打开了noImplicitAny,给所有隐式的any添加了类型,你的类型真的安全吗?答案是不!any依旧可以潜入你的代码,通过这几种方法:
- 当你采用技巧38,技巧39的方法,将any变为 any[]或者{[key: string]: any}。虽然明面的any消失了,当你引入变量的属性时,将会引入any。
- 来自第三方库。虽然你打开了noImplicitAny,你也没有输入过any,但也有可能通过第三方库流入你的代码。
由于any的副作用,你最好能跟踪你的any的数量,有很多方法可以实现这一点,其中就有 type-coverage:
$ npx type-coverage
9985 / 10117 98.69%
10117表示项目里面有10117个符号。同时该项目有9985个非any类型的符号。如果一个改变不经意引入了any类型,98.69%就会下降。同时这个百分数越高标志着你越听从该本书的意见。
运行type-coverage加上--detail参数能获取所有any类型的符号,以及出现的位置:
$ npx type-coverage --detail
path/to/code.ts:1:10 getColumnInfo
path/to/module.ts:7:1 pt2
...
这值得仔细看,你有可能发现你没有注意到的any类型的变量。显性any类型变量大多数是你自己的选择。用any断言能阻止any到处流窜。
假如你正在建立一个应用处理表列数据,你需要一个函数,该函数需要一个参数,同时能建立对列的描述:
function getColumnInfo(name: string): any {
return utils.buildColumnInfo(appState.dataSchema, name); // Returns any
}
因为utils.buildColumnInfo返回any类型,所以为了提醒,你标注getColumnInfo返回any类型。然而过了几个月,你为ColunmInfo添加了类型,utils.buildColumnInfo不再返回any类型。那么你标注的any阻止了getColumnInfo返回正确的类型。
第三方库引入any也有几种方法,但最极端的情况是,当你给整个模块一个任意类型:
declare module 'my-module';
你从my-module引入任何符号都不会报错,因为都是any类型:
import {someMethod, someSymbol} from 'my-module'; // OK
const pt1 = {
x: 1,
y: 2,
}; // type is {x: number, y: number}
const pt2 = someMethod(pt1, someSymbol); // OK, pt2's type is any
这看起来像类型友好的模块,但是往往被忽略的是你将整个模块的类型破坏。 所以需要时不时注意该模块是否有已经声明好的类型,没有的话你可以贡献相应的类型给社区。
第三方库引入any还有一种情况:type有bug。也许type声明没有听从技巧29:声明的函数返回类型是个联合type。当你第一次使用这个函数的时候,修复返回类型觉得麻烦,直接用any标注。但是,如果之后不好的声明被修复了。