TypeScript中互斥递归Filter类型的实现问题
TypeScript中互斥递归Filter类型的实现问题
你好呀!当然可以实现你想要的这种互斥递归Filter类型,你的思路方向是对的,只是之前的联合类型写法有点小问题,我来帮你捋清楚。
首先先回顾下你已经搭好的基础类型:
enum Operator { AND = 'AND', OR = 'OR', } type Filter = { column: string; rule: string; value: number | string | undefined; };
你的核心需求是:每一层的逻辑结构(OperatorHierarchy)只能包含AND或OR其中一个操作符,不能同时存在,而且可以无限嵌套多层,每层的操作符可以自由切换。
你之前尝试用void来实现互斥,但其实TypeScript里更直接清晰的方式是把OperatorHierarchy定义成两个对象类型的联合——每个类型只包含一个操作符属性,这样自然就做到了互斥:
type OperatorHierarchy = | { [Operator.AND]: Array<Filter | OperatorHierarchy> } | { [Operator.OR]: Array<Filter | OperatorHierarchy> };
咱们来验证下这个类型是否完全匹配你的需求:
首先,你之前写的flower示例对象完全可以正常使用,TypeScript会正确识别它的嵌套结构:
const flower: OperatorHierarchy = { [Operator.AND]: [ { column: 'plant', rule: 'is', value: 'flower' }, { [Operator.OR]: [ { column: 'leaf', rule: 'is', value: 'green' }, { [Operator.AND]: [ { column: 'leaf', rule: 'is', value: 'brown' }, { column: 'petal', rule: 'is', value: 'yellow' }, ] }, ] } ], };
如果有人不小心写出同时包含AND和OR的结构,TypeScript会直接报错,完美实现互斥校验:
// ❌ 这会报错:同时存在AND和OR,不符合联合类型的任何一个成员 const invalidFilter: OperatorHierarchy = { [Operator.AND]: [{ column: 'a', rule: 'is', value: 'b' }], [Operator.OR]: [{ column: 'c', rule: 'is', value: 'd' }] };
为啥你之前的写法行不通呢?因为你用void标记不允许的属性,但void在TypeScript里表示属性值为undefined,可对象属性本身是可以省略的,这种写法反而把类型定义搞复杂了,不如直接用联合类型明确“要么只有AND,要么只有OR”来得直观。
另外,这个类型定义天然支持无限嵌套,完全满足你“多层切换AND/OR”的需求——每一层的数组元素既可以是基础的Filter条件,也可以是下一层的OperatorHierarchy结构。
如果之后你需要扩展Operator枚举(比如加个NOT操作符),只需要在联合类型里新增一个对应的对象类型就行,扩展性也拉满。
内容来源于stack exchange
相关产品推荐
相关产品推荐

