FlowType中密封协变对象与$Exact+$ReadOnly的区别及类型定义对比
密封协变对象与$Exact+$ReadOnly在Flow中的区别,以及两个MovieType定义的对比
嘿,这个问题问到点子上了!咱们一步步拆解清楚Flow里这些类型工具的差异,还有你给出的两个类型定义到底是不是一回事。
先理清几个核心概念
- 密封对象语法
{| ... |}:这是Flow中$Exact<T>的语法糖,用来定义精确类型——意思是这个类型的对象只能包含定义里列出的属性,绝对不能有额外的未声明属性。 - 属性修饰符
+:在对象属性前加+,表示该属性是只读(readonly)且协变的。协变的简单理解是:如果类型A是类型B的子类型,那包含+A属性的对象可以赋值给包含+B属性的对象(更具体的类型能兼容更宽泛的类型)。 $ReadOnly<T>:这是批量处理的类型工具,能把传入的对象类型T的所有属性都变成只读,但它不管“精确性”——比如$ReadOnly<{ name: string }>的对象,还是能合法包含额外属性,除非再套上$Exact。$Exact<T>:单独使用时,只保证类型是精确的,但不会改变属性的可读写状态。
密封协变对象({| +... |})与$Exact<$ReadOnly<...>>的区别
如果是给整个对象的所有属性都加+修饰符,那{| +prop1: T1, +prop2: T2 |}和$Exact<$ReadOnly<{ prop1: T1, prop2: T2 }>>在功能上是等价的,但两者有语法层面的灵活性差异:
- 前者是逐个属性标记只读协变,你可以灵活地给部分属性加
+,部分不加(比如{| +name: string, age: number |},name是只读协变,age是可写状态); - 后者是批量处理所有属性为只读,再套精确类型——如果想给不同属性设置不同的可读写/变异性,后者就做不到,必须手动调整内部对象的属性修饰符。
简单总结:密封协变对象语法更灵活,适合精细化控制单个属性;$Exact+$ReadOnly是批量操作,适合让整个对象所有属性都只读且精确的场景。
两个MovieType类型定义的差异分析
看你给出的两个定义:
类型1:
type MovieType = {| +blob?: string, +name: string, +url?: string |};
类型2:
type MovieType = $Exact<$ReadOnly<{ blob?: string, name: string, url?: string }>>;
这两个类型在功能上完全等价,前者确实可以看作是后者的语法糖!原因如下:
{| ... |}本身就是$Exact<...>的语法糖;- 每个属性前的
+等价于标记该属性为readonly,而$ReadOnly<{...}>就是批量把所有属性标记为readonly; - Flow中readonly属性默认就是协变的,所以两种方式定义出来的类型,在属性的可读写性、协变性、精确性上完全一致。
不过要注意:如果类型1中有的属性不加+,那两者就不等价了——比如类型1是{| blob?: string, +name: string, url?: string |},只有name是只读协变,而类型2会把所有属性都变成只读协变,这时候差异就出现了。
内容的提问来源于stack exchange,提问作者Gajus
相关产品推荐
相关产品推荐

