Skip to content

观察:QueryParams.$filter 声明为 Record< string, any >,但仓内下沉口早已往里送 ObjectQL AST 数组 #3909

Description

@yinlianghui

观察类发现(finding,不进 pm:queue),发现于 #3831 / PR #3908 的实施过程。运行时正确、今天没有用户会撞到 —— 是类型面与实际契约的漂移。

机制

packages/types/src/data.ts:53 声明:

/**
 * Filter expression
 * @example { age: { $gt: 18 }, status: 'active' }
 */
$filter?: Record< string, any >;

即只描述 MongoDB 风格的 field-keyed 记录形式。但仓内规范下沉口 packages/core/src/utils/filter-converter.tstoFilterNode / mergeFilterNodes 返回的是 FilterNode | Record< string, any > | undefined —— AST 数组是其正常返回值之一,而两个既有消费者一直把它送进 $filter:

  • packages/plugin-list/src/ListView.tsxbuildEffectiveFilter(baseFilter: unknown, …),返回 any[] | Record< string, any > | undefined(喂表格与导出两条路);
  • packages/plugin-view/src/ObjectView.tsx(calendar / kanban / gallery / timeline)。

数据源侧完全支持:packages/data-objectstack/src/index.tstranslateFilterToAST 明确列出五种可接受输入,数组形式在列。所以运行时是对的,声明是窄的

有害在哪(只有类型面)

  1. 该类型不设防且方向错误:Record< string, any > 会接受数组(数组满足 any 的字符串索引 —— tsc --strict 实测 exit 0),所以它既没挡住不该进的形状,也没描述该进的形状。record:related_list.add.picker.filter 全仓零读点:作者限定了 Add 选择器的候选范围,对话框照样提供该对象的全部记录 #3831 正是踩在这一点上:baseFilter?: Record< string, any > 接受了规则数组、随后被对象展开压成 {"0": {...}},类型全绿而查询去过滤名为 0 的列。
  2. 新写消费者的人读 $filter 的类型与 @example,会以为只有记录形式合法,于是可能给数组路径补一段"容错转换" —— 正是 AGENTS.md #0.1 反对的方向。

落地建议

$filter 声明成它实际接受的联合(记录形式 | AST 节点),@example 补一条数组示例,并在注释里指名 translateFilterToAST 为权威可接受集。属 packages/types 公共面,会波及若干消费者的类型标注,故不宜搭在功能 PR 上 —— PR #3908 只在单个赋值点(packages/fields/src/widgets/useRecordQuery.ts)就地转换并注明原因,没有顺手改这个共享类型。

参考位置

  • packages/types/src/data.ts:53(声明)
  • packages/core/src/utils/filter-converter.ts(toFilterNode / mergeFilterNodes 的返回类型)
  • packages/plugin-list/src/ListView.tsx(buildEffectiveFilter)/ packages/plugin-view/src/ObjectView.tsx(两个既送数组的生产者)
  • packages/data-objectstack/src/index.ts(translateFilterToAST,实际可接受集)

关联:#3831 / PR #3908(发现来源)、#3948(两份 operator 词汇表漂移的先例)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions