You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从可辨识联合中选取属性子集并保证类型安全?

解决方案

你遇到的核心问题是原有FilterSet的定义是全局交叉类型,filters字段取的是全量Filter联合的字段类型,自然会合并所有可能的selectedModifier。只需要把FilterSet也定义为和Filter一一对应的分布式可辨识联合即可:

type FilterSet = Filter extends infer F 
  ? F extends Filter 
    ? Pick<F, 'fieldType' | 'fieldName' | 'availableModifiers'> & {
        filters: Pick<F, 'selectedModifier' | 'selectedValues'>[]
      }
    : never
  : never

实现效果

这个定义会自动遍历Filter联合的每一个成员(StringFilter/NumberFilter),为每个类型单独生成对应的FilterSet结构:

  • 当fieldType为'string'时,filters数组的selectedModifier自动限制为Mod1类型
  • 当fieldType为'number'时,filters数组的selectedModifier自动限制为Mod2类型

测试示例

// 合法:string类型FilterSet,修饰符只能用Mod1
const stringFilterSet: FilterSet = {
  fieldType: 'string',
  fieldName: 'userName',
  availableModifiers: ['eql', 'contains'],
  filters: [
    { selectedModifier: 'contains', selectedValues: ['test'] }
    // 此处填'gt'/'lt'等数字修饰符会直接抛出类型错误
  ]
}

// 合法:number类型FilterSet,修饰符只能用Mod2
const numberFilterSet: FilterSet = {
  fieldType: 'number',
  fieldName: 'age',
  availableModifiers: ['gt', 'lt'],
  filters: [
    { selectedModifier: 'gt', selectedValues: ['18'] },
    { selectedModifier: 'lt', selectedValues: ['30'] }
    // 此处填'contains'等字符串修饰符会直接抛出类型错误
  ]
}

扩展性说明

后续如果新增其他字段类型(比如日期类型'date'),只需要新增对应的DateFilter接口加入Filter联合,FilterSet会自动适配新类型,无需修改原有定义。


内容的提问来源于stack exchange,提问作者Ryno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 09:45:02