我有这个功能,它基本上将(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:我已经试过了,但在遇到像过载候选匹配不好的问题时暂停了一下。
答案 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>
但这又是另一天的痛苦。