对象上的流类型

Flow types on objects

我一直在考虑将 Flow 添加到我的 javascript 项目中。

在某些情况下,我做这样的事情,我有一个对象。

const myObject = {
    x: 12,
    y: "Hello World"
}

我有一个通用函数,可以对对象进行一些映射,保留键但替换值。

function enfunctionate(someObject) {
   return _.mapValues(myObject, (value) => () => value)
}

我想要 return 类型的函数 {x: () => number, y: () => string} 有办法实现吗?

当然,我可以将其更通用地键入为 {[key: string]: any},但我会失去很多我想通过使用流程获得的静态类型。

如果我可以用可以工作的代码生成或宏替换我执行此操作的几个案例,但我没有看到使用流程执行此操作的好方法。

有没有办法解决这个问题?

Flow 可以推断出很多东西。但是,如果您想固定类型,则必须自己创建类型。您需要为传递给 enfunctionate 的对象创建一个类型,然后指定 returned.

的类型

您可以使用 type alias 键入函数。因此,您可以为该函数创建一个新的显式类型。

function enfunctionate<X, Y>(x: X): Y {
    return _.mapValues(myObject, (value) => () => value)
}

只要知道 X 的类型,就知道 Y 的类型。类型别名、泛型和联合应该能够为您提供所需的灵活性。

但是,我也在想,只要 mapValues 的类型指定得很好(希望由其他人指定),那么您只需指定 enfunctionate 的类型就可以了让 Flow 推断出该函数的 return 类型。

这是目前你能得到的最好的,虽然它比 {[key: string]: any} 更安全,但仍然涉及 any

function enfunctionate<O: Object>(someObject: O): { [key: $Keys<O>]: (...rest: Array<void>) => any } {
   return _.mapValues(someObject, (value) => () => value)
}

const obj = enfunctionate(myObject)

obj.x() // ok
obj.unknown() // error

编辑:从 v.33 开始,您可以使用 $ObjMap

function enfunctionate<O>(o: O): $ObjMap<O, <V>(v : V) => () => V> {
  return _.mapValues(o, (value) => () => value)
}