首页 > 解决方案 > 我将如何键入命令工厂函数?

问题描述

这是我正在尝试流类型的简化示例。考虑这个函数......

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

我想从 Flow 中输入这个函数... * auth 和 exec 都是具有相同输入(可以是任意数量的输入)的异步函数 * auth 是一个 void 函数(返回 Promise,因为它是异步的) * 返回的函数createCommand 应该返回与 exec 返回相同的东西(希望返回说明清楚) * 如果所有这些都是可行的,那么再扩展一个!auth 和 exec 必须始终具有特定类型的第一个参数!

标签: flowtype

解决方案


您的主要问题是您正在尝试编写多态函数,但您没有将其注释为多态。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)
}

试流链接

基本上,您必须显式地注释Args它们Ret出现在类型中的任何位置,以便 Flow 将这些类型识别为多态。如果您在某处遗漏了注释,则 Flow 会推断该类型是单态的。


推荐阅读