持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
本文的翻译于<<Effective TypeScript>>, 特别感谢!! ps: 本文会用简洁, 易懂的语言描述原书的所有要点. 如果能看懂这文章,将节省许多阅读时间. 如果看不懂,务必给我留言, 我回去修改.
技巧61:一个模块一个模块地转换你的依赖图
当你已经用让了先进的js语法,也将ts纳入你的构建链,同时也能通过你所有的单元测试。那问题来了,该从哪开始将你的js转换成ts呢?
当你给一个模块添加了type,很有可能所有依赖该模块的模块将会报错。理想情况是你一个模块一个模块的去添加type。 这就好像,从依赖图的叶子节点慢慢修改到根节点。
第一个应该迁移的模块应该是第三方依赖。因为你依赖了它们,但是它们没有依赖你。通常你只要安装相应的@types就可以,例如lodash模块:
npm install --save-dev @types/lodash
这些typings帮助type在你的代码中流动,同时让你的错误浮现。
如果你的代码调用了额外的APIs,你也应该给它们添加types,因为你依赖了它们,但是它们没有依赖你。添加依赖的方法见技巧35。
迁移你自己的模块的时候,用某些工具对你的依赖图进行可视化非常有用。例如,madge工具。
当你将js换成ts过程中,你会遇到一些常见的错误:
未声明的class 属性
class在js中不需要声明它的属性,但是ts中的class需要。当你将.js后缀改为.ts后缀,会报这样的错:
class Greeting {
constructor(name) {
this.greeting = 'Hello';
// ~~~~~~~~ Property 'greeting' does not exist on type 'Greeting'
this.name = name;
// ~~~~ Property 'name' does not exist on type 'Greeting'
}
greet() {
return this.greeting + ' ' + this.name;
// ~~~~~~~~ ~~~~ Property ... does not exist
}
}
当然有一个快速修复的方法,你可以使用:
这会根据使用添加属性:
class Greeting {
greeting: string;
name: any;
constructor(name) {
this.greeting = 'Hello';
this.name = name;
}
greet() {
return this.greeting + ' ' + this.name;
}
}
ts正确添加了greeting的type,但是错误添加了name的type。在快速修复后,你需要检查一遍属性列表,对不正确的type的进行修复。
改变types的values
ts可能会这样报错:
const state = {};
state.name = 'New York';
// ~~~~ Property 'name' does not exist on type '{}'
state.capital = 'Albany';
// ~~~~~~~ Property 'capital' does not exist on type '{}'
这个错误在技巧23讲解的更深入。如果你遇到这个错误,可以对state进行显性类型声明:
const state = {
name: 'New York',
capital: 'Albany',
}; // OK
如果你的state不是这个type,你还可以这样做:
interface State {
name: string;
capital: string;
}
const state = {} as State;
state.name = 'New York'; // OK
state.capital = 'Albany'; // OK
如果你是用JSDoc和@ts-check,你需要意识到:当你让js转成ts可能会丢失类型安全。 例如@ts-check可能会这样报错:
/ @ts-check
/**
* @param {number} num
*/
function double(num) {
return 2 * num;
}
double('trouble');
// ~~~~~~~~~ Argument of type '"trouble"' is not assignable to
// parameter of type 'number'
当你转成ts后,@ts-check会自动停止,上面有意义的报错会停止:
/**
* @param {number} num
*/
function double(num) {
return 2 * num;
}
double('trouble'); // OK
幸运的是这类错误也有快速修复:
一但你添加了type,记得把JSDoc及时删除。
最后迁移你的test,它们应该在你的依赖图的上方。这非常重要:在迁移的过程中能通过测试。