React HOC开发中$Diff处理交叉类型报错问题咨询
搞定$Diff处理交叉类型时的报错问题
嘿,我碰到过类似的情况,刚好能帮你解决这个问题!
问题出在哪?
你写的这段代码里,$Diff<All, Three>报错,核心原因是$Diff这个工具类型对交叉类型的支持不够友好。All是One & Two & Three的交叉类型,它的属性是三个类型的合并,但$Diff的实现逻辑通常是基于对象的显式属性列表,没办法正确识别交叉类型里哪些属性来自Three,所以当你试图用它移除Three的属性时,就会出现类型不兼容的报错。
看你的示例代码:
type One = { one: number } type Two = { two: number } type Three = { three: number } type Both = One & Two type All = Both & Three const both:$Diff<All, Three> = { one: 1, two: 2 }
报错提示“未定义属性three与number类型不兼容”,本质就是$Diff没正确处理交叉类型的属性推导。
怎么解决?
我们自己写一个能处理交叉类型的差异类型就行,用TypeScript的原生工具类型组合实现:
// 自定义Diff类型,完美支持交叉类型 type Diff<T, U> = Pick<T, Exclude<keyof T, keyof U>>;
把原来的$Diff换成这个Diff,代码就正常运行了:
type One = { one: number } type Two = { two: number } type Three = { three: number } type Both = One & Two type All = Both & Three const both: Diff<All, Three> = { one: 1, two: 2 } // 完全没问题,不会再报错
原理是什么?
这个自定义类型的逻辑很清晰:
keyof T拿到交叉类型All的所有键:"one" | "two" | "three"Exclude<keyof T, keyof U>把属于Three的键"three"排除掉,剩下"one" | "two"Pick<T, ...>从All里挑出剩下的键对应的类型,最终得到和One & Two完全等价的类型
如果是在Flow环境下,也可以用类似的思路自定义适配交叉类型的Diff:
type Diff<T, U> = $ObjMap<T, <K>(K => $Conditional<K extends keyof U, void, T[K]>)>;
小提示
在写React高阶组件处理交叉类型props的时候,这个自定义的Diff类型能帮你精准排除掉不需要传给子组件的属性,再也不会出现类型不匹配的问题啦!
内容的提问来源于stack exchange,提问作者Douglas Meyer
相关产品推荐
相关产品推荐

