本文的翻译于<<Effective TypeScript>>, 特别感谢!! ps: 本文会用简洁, 易懂的语言描述原书的所有要点. 如果能看懂这文章,将节省许多阅读时间. 如果看不懂,务必给我留言, 我回去修改.
技巧41:理解any进化
ts的变量类型一般在声明的时候已经定好了。声明之后,可以对类型进行细化,但是不能扩展。 但是有个例外:any的进化。
在js中你可能会写一个函数:用于根据范围产生一列数:
function range(start, limit) {
const out = [];
for (let i = start; i < limit; i++) {
out.push(i);
}
return out;
}
将其转为ts:
function range(start: number, limit: number) {
const out = [];
for (let i = start; i < limit; i++) {
out.push(i);
}
return out; // Return type inferred as number[]
}
这里十分神奇的是,当out开始声明的时候,是any[]类型,到最后类型进化为:number[]。可以仔细查看每个out的类型:
function range(start: number, limit: number) {
const out = []; // Type is any[]
for (let i = start; i < limit; i++) {
out.push(i); // Type of out is any[]
}
return out; // Type is number[]
}
当我们把number 放入out中时,out类型会自动进化成 number[]
当有条件语句,any进化可以在不同分支发生,进化成不同类型:
let val; // Type is any
if (Math.random() < 0.5) {
val = /hello/;
val // Type is RegExp
} else {
val = 12;
val // Type is number
}
val // Type is number | RegExp
还有一种情况能引起 any进化。当val的初始值为null时,在try,catch可能会引起any进化:
let val = null; // Type is any
try {
somethingDangerous();
val = 12;
val // Type is number
} catch (e) {
console.warn('alas!');
}
val // Type is number | null
有趣的是:any进化,只发生在隐式any,同时没有设置noImplicitAny:
let val: any; // Type is any
if (Math.random() < 0.5) {
val = /hello/;
val // Type is any
} else {
val = 12;
val // Type is any
}
val // Type is any
当我们在赋值之前使用隐式any,会报错:
function range(start: number, limit: number) {
const out = [];
// ~~~ Variable 'out' implicitly has type 'any[]' in some
// locations where its type cannot be determined
if (start === limit) {
return out;
// ~~~ Variable 'out' implicitly has an 'any[]' type
}
for (let i = start; i < limit; i++) {
out.push(i);
}
return out;
}
any进化只有对隐式any赋值的时候才会发生,当你对隐式any用读操作,就会得到错误。
隐式any函数调用后不会进化:
function makeSquares(start: number, limit: number) {
const out = [];
// ~~~ Variable 'out' implicitly has type 'any[]' in some locations
range(start, limit).forEach(i => {
out.push(i * i);
});
return out;
// ~~~ Variable 'out' implicitly has an 'any[]' type
}
在ts中最常见的警告都是隐式any的,我们尽可能的要使用显示类型,让ts通过更精准类型检查