[译]<<Effective TypeScript>> 技巧38:尽可能限制 any 作用的范围

99 阅读2分钟

本文的翻译于<<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
  }
};