我尝试使用 promisify 的打字版本,这是一种将带有节点回调的函数转换为本机promises的方法,以便在等待异步时使用它们。
其中一种类型签名如下:
function promisify<A1, A2, R1>(
nodeFunction: (
arg1: A1,
arg2: A2,
callback: (err: any, r1: R1) => any
) => any,
arg1 : A1,
arg2 : A2): Promise<R1>
这是一个节点函数,它接受两个参数并在回调上返回一个值,例如fs.readFile
,请注意,由于readFile
有多个调用签名,该函数会询问这些参数所以我们可以推断A1
和A2
明确的泛型工作,但编译器无法推断类型,编译器的消息是:
The type argument for type parameter 'A2' cannot be inferred from the usage.
Consider specifying the type arguments explicitly.
Type argument candidate '(err: ErrnoException, data: Buffer) => void'
is not a valid type argument because it is not a supertype of candidate 'string'.
readfile
签名:
readFile(filename: string, encoding: string,
callback: (err: NodeJS.ErrnoException, data: string) => void): void;
如果我们在函数调用上传递两个字符串,那么唯一的重载是接受第二个参数上的字符串:
promisify(fs.readFile, 'file.txt', 'utf8')
为什么编译器选择了接受对象的重载而不是第二个参数上的字符串?
由于arg2
肯定是字符串('utf8'
),编译器应该知道A2
是字符串,然后只选择接受string
作为第二个参数的重载
这些都是签名:
export function readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
export function readFile(filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
export function readFile(filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void;
export function readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void;