本文的翻译于<<Effective TypeScript>>, 特别感谢!! ps: 本文会用简洁, 易懂的语言描述原书的所有要点. 如果能看懂这文章,将节省许多阅读时间. 如果看不懂,务必给我留言, 我回去修改.
技巧38:尽可能限制 any 作用的范围
考虑到这段代码:
function processBar(b: Bar) { /* ... */ }
function f() {
const x = expressionReturningFoo();
processBar(x);
// ~ Argument of type 'Foo' is not assignable to
// parameter of type 'Bar'
}
如果你想让ts强制忽略这个错误,有两个方法:
function f1() {
const x: any = expressionReturningFoo(); // Don't do this
processBar(x);
}
function f2() {
const x =
expressionReturningFoo();
processBar(x as any); // Prefer this
}
最好选用第二个方法,因为断言只会作用断言所在的那一行。不会在其他代码行产生影响。第一个方法恰恰相反,影响的范围非常大,有可能会超出函数f1本身:
function f1() {
const x: any = expressionReturningFoo();
processBar(x);
return x;
}
function g() {
const foo = f1(); // Type is any
foo.fooMethod(); // This call is unchecked!
}
如果一个函数的返回类型是any,那么就会将any类型传染到代码库的其他地方。 上面代码中,f1返回any 类型的变量,foo就是any类型。g函数有可能将foo传染到其他地方。(所以说,我们最好提前定义好函数的返回类型,这样就能防止any传染出来)
如果说我们知道用any去掩盖这个错误是不对的,那么我们还有一个方法:用 @ts-ignore:
function f1() {
const x = expressionReturningFoo();
// @ts-ignore
processBar(x);
return x;
}
@ts-ignore也仅仅作用下面的一行代码,也不会改变x的类型。但是我们也不要过分依赖@ts-ignore。ts报错往往是有原因的,找到这个原因,然后解决这个报错,往往能让我们避免很多错误。
你也 有可能遇到在一个大的object中,单个属性的报错:
const config: Config = {
a: 1,
b: 2,
c: {
key: value
// ~~~ Property ... missing in type 'Bar' but required in type 'Foo'
}
};
想要掩盖这个报错,可以对整个object标注为any:
const config: Config = {
a: 1,
b: 2,
c: {
key: value
}
} as any; // Don't do this!
但是副作用就是:ts不会对其他正常的属性值进行检查。更好的做法是,限制any的作用范围:
const config: Config = {
a: 1,
b: 2, // These properties are still checked
c: {
key: value as any
}
};