如何键入命令工厂功能?

时间:2019-06-06 20:13:16

标签: flowtype

这是我尝试使用Flow类型的简化示例。考虑这个功能...

const createCommand = ({
    auth,
    exec,
} => async (...args) => {
    await auth(...args)
    return exec(...args)
}

我想要Flow键入此功能的东西... * auth和exec都是异步函数,具有相同的输入(可以是任意数量的输入) * auth是一个无效函数(因为它是异步的,所以返回Promise) * createCommand返回的函数应该返回exec返回的相同内容(希望返回可以清楚地看到) *如果所有这些都可行,请再扩展一次! auth和exec必须始终具有特定类型的第一个参数!

1 个答案:

答案 0 :(得分:0)

您的主要问题是您试图编写多态函数,但尚未将其注释为多态函数。 Flow总是推断函数是单态的。这是使用身份函数的示例:

const badIdentity = x => x;
(badIdentity(123): number); // Error - cannot cast string to number
(badIdentity("hello"): string); // Error - cannot cast number to string

我们希望badIdentity是身份函数,它是多态的。但是,由于未使用类型参数(即<...>)进行显式注释,因此Flow会将其推断为单态,并根据函数调用猜测x的类型。在此示例中,Flow会推断badIdentity

(x: (number | string)) => (number | string)

要解决此问题,必须提供类型参数。

const goodIdentity = <T>(x: T): T => x;
(goodIdentity(123): number); // Ok
(goodIdentity("hello"): string); // Ok

您还可以通过在createCommand函数中添加显式类型参数来解决您的具体情况

const createCommand = <Args: $ReadOnlyArray<mixed>, Ret>({
    auth,
    exec,
} : {
    auth: (...Args) => Promise<mixed>,
    exec: (...Args) => Ret,
}): (...Args) => Promise<Ret> => async (...args) => {
    await auth(...args)
    return exec(...args)
}

try-flow link

基本上,您必须在类型中出现的ArgsRet处进行显式注释,以便Flow将这些类型识别为多态的。如果您在某处缺少注释,则Flow会推断该类型为单态。