在FlowJS中递归创建ReadOnly对象

Sam*_*Sam 6 recursion flowtype redux

在redux中,状态应该是不可变的。我希望Flow可以防止任何人改变该状态。因此,给定任意深度的对象:

type object = {
  a: {
    b: {
      d: string
    }
  },
  c: number
}
Run Code Online (Sandbox Code Playgroud)

我如何创建一个递归只读的新类型,所以我不能这样做:

let TestFunction = (param: $RecursiveReadOnly<object>) => {
  param.a.b.d = 'some string'
}
Run Code Online (Sandbox Code Playgroud)

$ReadOnlyFlow 的内置实用程序将创建这样的类型,这不是必需的,因为bd仍可写:

{
  +a: {
    b: {
      d: string
    }
  },
  +c: number
}
Run Code Online (Sandbox Code Playgroud)

我一直在尝试使用$Call$ObjMap(i),但是我不知道如何在Flow中递归地移动对象。目的是要做到这一点:

{
  +a: {
    +b: {
      +d: string
    }
  },
  +c: number
}
Run Code Online (Sandbox Code Playgroud)

Sam*_*Sam 5

感谢kalley的解决方案。据我了解,kalley试图使函数接收的任何对象都递归地只读。由于我实际上只需要将已知对象用作参数,因此可以完美地工作:

// Type definition that works with arbitrary nested objects/arrays etc.
declare type RecursiveReadOnly<O: Object> = $ReadOnly<$ObjMap<O, typeof makeRecursive>>
declare type RecursiveReadOnlyArray<O: Object> = $ReadOnlyArray<$ReadOnly<$ObjMap<O, typeof makeRecursive>>>
type Recursive<O: Object> = $ObjMap<O, typeof makeRecursive>

declare function makeRecursive<F: Function>(F): F
declare function makeRecursive<A: Object[]>(A): $ReadOnlyArray<$ReadOnly<Recursive<$ElementType<A, number>>>>
declare function makeRecursive<O: Object>(O): RecursiveReadOnly<O>
declare function makeRecursive<I: string[] | boolean[] | number[]>(I): $ReadOnlyArray<$ElementType<I, number>>
declare function makeRecursive<I: string | boolean | number | void | null>(I): I

// Usage example.
type obj = {
  a: {
    b: {
      d: string,
    }
  }
}


let TestFunction = (param: RecursiveReadOnly<obj>) => {
  param.a.b.d = 'some string' // Flow throws an error
}
Run Code Online (Sandbox Code Playgroud)