认识TypeScript和可替代性

127 阅读3分钟

在开始使用TypeScript时,没有花多少时间就偶然发现了类型系统的一些赔率。如果你仔细观察,这些赔率是很有意义的。在这篇文章中,我想告诉你为什么以及在某些情况下,TypeScript允许非匹配的方法签名。

具有较少参数的函数#

使用TypeScript,将函数传递给其他指定参数较少的函数是可以的。请看下面的例子。

fetchResults 有一个参数,一个回调函数。该方法从某处获取数据,之后执行一个回调。回调的方法签名有两个参数。 (类型 )和结果( 的数组)。你在第4行看到了这个调用。statusCode number number

function fetchResults(callback: (statusCode: number, results: number[]) => void) {
  // get results from somewhere
  ...
  callback(200, results); // this is line 4
}

我们用下面的handler 函数调用fetchResults 。不过,这个方法的签名是不同的。它省略了第二个参数results

function handler(statusCode: number) {
  // evaluate the status code
  ...
}

fetchResults(handler); // compiles, no problem!

这仍然是在没有任何错误或警告的情况下编译的。这首先让人感觉很奇怪,尤其是在与其他语言进行比较时。为什么不匹配的方法签名会被接受?但是TypeScript是JavaScript的一个超集。如果你仔细想一想,我们在JavaScript中一直在做这样的事情!

express ,即服务器端框架为例。回调方法通常有三个参数。

  • req: 原始请求
  • res:服务器的响应
  • next: 传递给堆栈中的下一个中间件。

如果不需要调用下一个中间件,我们可以省略next 这个参数。

其力量在于回调函数。回调函数最清楚该如何处理移交的所有参数。而如果不需要某个参数,可以安全地跳过它。

返回类型 void#

如果一个函数类型指定了返回类型void ,那么也可以接受不同的、更具体的返回类型的函数。还是之前的那个例子。

function fetchResults(callback: (statusCode: number, results: number[]) => void) {
  // get results from somewhere
  ...
  callback(200, results);
}

回调函数的签名中有两个参数,而返回类型是void 。让我们看看之前的一个适应性处理函数。

function handler(statusCode: number): boolean {
  // evaluate the status code
  ...
  return true;
}

fetchResults(handler); // compiles, no problem!

尽管方法签名声明了一个布尔型的返回类型,代码仍然可以编译。尽管方法签名并不匹配。当声明一个void 的返回类型时,这一点很特别。原来的调用者fetchResults ,在调用回调时不期望有返回值。

如果我们真的将结果分配给fetchResult 内的变量或常量,TypeScript 会抛出一个错误。

function fetchResults(callback: (statusCode: number, results: number[]) => void) {
  // get results from somewhere
  ...
  const didItWork = callback(200, results); // ⚡️ compile error!
}

这就是为什么我们可以传递任何返回类型的回调。即使回调返回了一些东西,这个值也不会被使用,而是进入了空洞。

权力就在调用函数中。调用函数最清楚应该从回调函数中期待什么。如果调用函数根本不需要回调函数的返回值,那么什么都可以。

可替代性#

TypeScript称这种特性为 "可替代性"。在任何有意义的地方,用一种东西代替另一种东西的能力。一开始,这可能会让你觉得很奇怪。但是,特别是当你与不是你编写的库一起工作时,你会发现这个功能非常有用。