本文的翻译于<<Effective TypeScript>>, 特别感谢!! ps: 本文会用简洁, 易懂的语言描述原书的所有要点. 如果能看懂这文章,将节省许多阅读时间. 如果看不懂,务必给我留言, 我回去修改.
技巧51:用镜像类型去切断依赖
假定你在写一个库用来解析CSV文件。你传入CSV文件的内容,返回一个对象构成的数组。为了使用方便,你允许传入内容可以是string或者NodeJS Buffer:
function parseCSV(contents: string | Buffer): {[column: string]: string}[] {
if (typeof contents === 'object') {
// It's a buffer
return parseCSV(contents.toString('utf8'));
}
// ...
}
Buffer类型来自于 NodeJS 的type声明,这样安装:
npm install --save-dev @types/node
当你发布你的CSV解析库,你将node的type声明加入依赖。那么会有两拨人会对这个声明依赖有抱怨:
- 想知道自己@types依赖的js开发者
- 想知道自己为啥会依赖NodeJs的ts web开发者:
这样的抱怨是合理的。Buffer的行为没有必要的,它只和NodeJS的使用者相关。
与其依赖node的type声明,不如自己写:
interface CsvBuffer {
toString(encoding: string): string;
}
function parseCSV(contents: string | CsvBuffer): {[column: string]: string}[] {
// ...
}
我们写的CsvBuffer类型,比完整的CsvBuffer类型更短。但是它确实满足了我们的需要(因为我们只要Buffer的toString方法)。当我们传入Buffer,类型是安全的:
parseCSV(new Buffer("column1,column2\nval1,val2", "utf-8")); // OK
如果我们的库依赖其他库的类型声明,与其用他的实现,不如我们将我们需要的类型进行镜像复制。这样减少了依赖,能提升其他人的开发体验。
当然如果我们依赖其他库的type声明特别多,那我们应该标注出来来来关系。
这个技巧对应写单元测试的小伙伴同样有效。