声明" promisifier"的类型打字稿或流程中的功能

时间:2017-04-24 19:38:04

标签: javascript typescript flowtype

我有这个功能,它基本上将(nodejs)回调式函数转换为promise样式函数。

export const promisify 
    : PromisifyT 
    = ( fn, ...args ) => {
        return new Promise( (resolve, reject) => {
            fn( ...args , (err, ...result) => {
                if (err) return reject(err)
                resolve(result)
            })
        }) as any
    }

我如何声明PromisifyT以便fn的输入类型正确映射到生成的函数? (由于仍然不支持可变参数类型参数,我们可以将自己限制为最多2或3个参数)。它甚至可能吗?

PS:我已经试过了,但在遇到像过载候选匹配不好的问题时暂停了一下。

1 个答案:

答案 0 :(得分:2)

这是可能的,它完全没有乐趣。

这是我所指的WHOLLY NOT FUN的类型:

const resolveWith = (resolve, reject) => (err, data) =>
    err ? reject(err) : resolve(data);

type Resolver = (err:any, data:any) => void;

type Nodelike1<A> = (x:A, resolver:Resolver)=>void;
type Nodelike2<A,B> = (x:A, y:B, resolver:Resolver)=>void;
type Nodelike3<A,B,C> = (x:A, y:B, z:C, resolver:Resolver)=>void;

function promisify <A>(fn:Nodelike1<A>, x:A):Promise<any>;
function promisify <A, B>(fn:Nodelike2<A,B>, x: A, y:B):Promise<any>;
function promisify <A, B, C>(fn:Nodelike3<A,B,C>, x:A, y:B, z:C):Promise<any>;
function promisify (fn, x, y?, z?) {
  if (z != null) {
    return new Promise((resolve, reject) =>
      fn(x, y, z, resolveWith(resolve, reject)));
  } else if (y != null) {
    return new Promise((resolve, reject) =>
      fn(x, y, resolveWith(resolve, reject)));
  } else {
    return new Promise((resolve, reject) =>
      fn(x, resolveWith(resolve, reject)));
  }
}

const readFile = promisify((url:string, cb) => cb(null, "Bob"), url);

如果传递的url有一个字符串,它将毫无障碍地工作。如果你传入一个数字,TypeScript会询问你是否还有别的东西,因为从它传递的函数的签名中,它需要一个字符串。

正如你所看到的,你可以将它延伸到夕阳中,然后把它变成一个快乐的300行长袋,里面装满了仿制品,然后通过参数列表向后翻。 作为一个喜欢函数式编程的人,你无法想象当我实现一个compose或一个咖喱时,这会让我感觉多么脏......他们是可怕的...这些类型让我的代码更加安全的想法case只有在我的代码首先是这样写的时候才是真的,而不是安抚编译器。

理想情况下,我会更进一步,让promisify返回一个函数,该函数期望参数xy和z与传入的函数分开,因此它只在系统中看起来很尴尬。 / p>

但这又是另一天的痛苦。