尝试流链接
我一直在输入一个"camel-caser"函数(一个使用JSON并对其键进行camel-case处理的函数)。一路上我遇到了一些问题,我很好奇你们是否有什么建议。
骆驼案件审理者永远不会改变其论点的形式,所以我想保留我所传递的任何内容的类型;理想情况下,在一个数字数组上调用camelize
会返回另一个数字阵列等。
我从以下内容开始:
type JSON = null | string | number | boolean | { [string]: JSON } | JSON[]
function camelize<J: JSON>(json: J): J {
throw "just typecheck please"
}
这对于简单的情况(null
、string
、number
和boolean
)非常有效,但对于JSON字典或数组来说,效果并不理想。例如:
const dictionary: { [string]: number } = { key: 123 }
const camelizedDictionary = camelize(dictionary)
将失败,并出现类型错误。如果您传入一个值,例如键入number[]
,也会出现类似的问题。我想我理解这个问题:数组和字典是可变的,因此它们所指向的值的类型是不变的;一个数字数组是而不是JSON[]
的子类型,因此Flow抱怨道。如果数组和字典是协变的,我相信这种方法会起作用。
考虑到它们不是协变的,你们对我应该如何看待这一点有什么建议吗?
Flow现在支持$ReadOnly
和$ReadOnlyArray
,因此另一种方法是将JSON
类型定义为
type JSON =
| null
| string
| number
| boolean
| $ReadOnly<{ [string]: JSON }>
| $ReadOnlyArray<JSON>
这解决了上述问题之一,因为$ReadOnlyArray<number>
是$ReadOnlyArray<JSON>
的亚型。
这可能不起作用,这取决于camelize
函数的实现,因为它可能会将键修改为驼色大小写。但是,了解Flow中的只读实用程序是很好的,因为它们功能强大,可以实现更简洁、可能更正确的函数类型。
使用属性方差来解决字典问题:
type JSON = null | string | number | boolean | { +[string]: JSON } | JSON[]
https://flowtype.org/blog/2016/10/04/Property-Variance.html
至于Arrays
的问题,正如您所指出的,问题在于可变性。不幸的是,Array<number>
不是Array<JSON>
的亚型。我认为获得所需内容的唯一方法是显式枚举所有允许的Array
类型:
type JSON = null | string | number | boolean | { +[string]: JSON } | Array<JSON> | Array<number>;
我在这里只添加了Array<number>
来表明我的观点。显然,这很麻烦,尤其是如果您还想包含任意混合的JSON元素(如Array<string | number | null>
)。但它有望解决共同的问题。
(我还将其更改为我更熟悉的数组语法,但功能上应该没有区别)。
有人说要添加Array
的只读版本,它类似于协变对象类型,我相信它会解决您的问题。但到目前为止,还没有什么真正的结果
根据你给出的内容完成试用流程。