在打字稿或流程中声明“promisifier”函数的类型
问题描述:
我有这个函数,它基本上将(nodejs)回调式函数转换为承诺式函数。在打字稿或流程中声明“promisifier”函数的类型
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:我已经给它一个尝试,但遇到像过载错误候选匹配等问题时暂停了一下。
答
这是可能的,它只是完全没有乐趣。
这完全是不好玩的类型,我是指:
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线长包,充满了仿制药的乐趣,并且通过参数列表向后走。 作为一个喜欢函数式编程的人,你无法想象当我实现一个写作或咖喱时,这让我感觉有多脏......他们很可怕......在这种情况下,这些类型让我的代码更安全只有当我的代码是这样写在第一位,而不是安抚编译器时才是如此。
理想情况下,我会进一步采取这一步骤并进行promisify
回报预期的参数x和y和z分别从功能上被传递的功能,使其不仅看起来这种尴尬的一次是在系统中。
但这是另一天的痛苦。
虽然我写我的答案,你可能确实意味着'作为承诺'在尾端。 ......理想情况下,你甚至不需要这个。 –
Norguard
我其实不想担心在函数实现中推断的类型,但我实际上并不需要这种类型的转换... –
没错。你明确地向任何人投射。该类型是'Promise'(或'Promise ')。但是,TypeScript可以愉快地推断没有帮助。这是一个问题,“你是为编译器的好处编写类型还是你的编写类型”(因为编译器可能不需要其中的大部分)。如果您试图推断Promise中包含的返回类型,它只需要帮助。 –
Norguard