在typescript下编写异步代码,会遇到难以自动识别异步返回值类型的情况,本文介绍一些技巧,以辅助编写更健全的异步代码。
callback
以读取文件为例:
readFile是一个异步函数,包含path和callback两个参数,callback的不进行声明类型的情况下,调用readFile后传入的callback无法正确识别到callback的err和rst的类型。通常在这种情况下,使用者很容易出现错用参数的情况,例如把rst当成一个字符串使用等。有了上面的类型描述后,下面的两种调用就能让编译器自动检测出错误:
Promise
一些可以将异步结果通过promise包装起来的函数,typescript的初学者可能一时找不到方法去描述Promise的异步结果类型。其实官方的描述文档中已经提供了Promise的相关描述。并提供了泛型描述接口Promise<type>来描述其异步的返回结果。
例如这样的一个函数,将返回值的类型定义为Promise<Buffer>,即表示该函数调用后返回的是一个异步结果为Buffer的Promise。
以下是常见的调用Promise异步函数的方法:
这样,无论是通过then还是await调用,都能严格检测到异步的返回结果(yield是一个例外,后面会提到)
Callback/Promise自动识别函数
这种函数形如:
这种函数的callback参数是可选的,如果传入callback,那么就通过回调的方式处理异步结果。如果不传入回调,那么就会返回一个Promise。
常见的两种调用方式:
泛型异步返回值
在没有typescript前,有很多的异步调用会更具不同的调用方式返回不同类型的结果。我们要兼容此部分代码,可以利用重载。但更好用一点的办法则是利用泛型来处理。
例如有这样的一个异步函数:
用于异步克隆对象。异步的返回类型要和调用时传入的类型相同。这里通过将参数originObj的类型限定为泛型TRst,将异步返回值的结果也限定为TRst来达到这样的目的。这个函数调用时,也不需要自动为函数加上类型,编译器会自动识别originObj的类型并将异步返回结果的类型设置为同样的类型。
yield与generator
目前在typescript下,在generator中使用yield,是难以得到异步返回类型的。
编译器会默认yield等待的结果类型是个any,因此建议使用async await替代,虽然最终编译结果相差不大。从yield切换到await有一些需要注意的地方,例如await不能直接等待Promise数组。