如何在Typescript中指定我想要的重载函数?

时间:2016-06-15 10:50:43

标签: node.js typescript

我试图宣传标准节点fs.writeFile。我有节点和蓝鸟的输入,这是我的Promise lib选择:

const f = Promise.promisify(fs.writeFile)
return f(file, content); // Should be a promise

这不起作用,因为:

  

[ts]提供的参数与呼叫目标的任何签名都不匹配。   const f:(arg1:string)=>无极< {}>

所以我选择了错误的重载方法,因为调用promisify并不能真正知道我猜的是什么。或者它甚至不是,但是带有可选参数的东西,因为这些是三个重载的writeFile:

export function writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void;
export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;
export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void;

promisify对于args有很多重载,看起来像这样:

/**
 * Returns a function that will wrap the given `nodeFunction`. Instead of taking a callback, the returned function will return a promise whose fate is decided by the callback behavior of the given node function. The node function should conform to node.js convention of accepting a callback as last argument and calling that callback with error as the first argument and success value on the second argument.
 *
 * If the `nodeFunction` calls its callback with multiple success values, the fulfillment value will be an array of them.
 *
 * If you pass a `receiver`, the `nodeFunction` will be called as a method on the `receiver`.
 */
static promisify<T>(func: (callback: (err:any, result: T) => void) => void, receiver?: any): () => Promise<T>;
static promisify<T, A1>(func: (arg1: A1, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1) => Promise<T>;
static promisify<T, A1, A2>(func: (arg1: A1, arg2: A2, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2) => Promise<T>;
static promisify<T, A1, A2, A3>(func: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2, arg3: A3) => Promise<T>;
static promisify<T, A1, A2, A3, A4>(func: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Promise<T>;
static promisify<T, A1, A2, A3, A4, A5>(func: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Promise<T>;
static promisify(nodeFunction: Function, receiver?: any): Function;

所以它似乎是使用错误的promisify。有没有更清洁的方式让我实现我想要的?目前我必须解决这个问题:

const writeFile : (filename: string, data: any, callback: (err: NodeJS.ErrnoException) => void) => void = fs.writeFile
const f = Promise.promisify(writeFile)
return f(file, content); 

我认为这是非常丑陋和冗长的......

2 个答案:

答案 0 :(得分:1)

我还没有能够设置一个简单的工作示例,但是下面的类型断言可以让你提示并提出你期望的内容:

const f = <(file: string, content: string) => void> Promise.promisify(fs.writeFile)

您可以修改<(file: string, content: string) => void>以更好地描述您希望提供的内容,或使用更广泛的类型<Function>或使用<any>动态。

第一个选项是更多的工作,但是当你稍后调用f(在这种情况下是void时 - 将允许推断返回类型 - 但你可以想象这种返回类型将会出现的情况得到更积极的使用)。

根据您的评论,我猜测您需要......

const f = <(file: string, content: string) => Promise<any>> Promise.promisify(fs.writeFile)

如果您知道两种可能的结果,也可以使用联合类型代替此示例中的any,即Promise<any>可能是:

Promise<ErrnoException | MySuccessfulType>

这将允许返回类型Promise<ErrnoException>或返回类型Promise<MySuccessfulType>

答案 1 :(得分:1)

您可以使用 __promisify__ 命名空间中的 fs.writeFile

fs.writeFile.__promisify__(file, content)

否则,您必须明确提及泛型类型以选择相应的重载:

  • Node 内置 util 包有一个 promisify() 函数
const f = util.promisify<PathLike, string, void>(fs.writeFile)
f(file, content)