如何创建按对象类型区分的数组类型?解决TS类型报错
问题分析
你遇到的报错是因为当前的TFilter类型没有正确关联type字段和data的类型约束。原来的条件类型写法是对整个TFiltersTypes联合类型做判断,导致data被推断为(TSelectableTabsFilterItem | TDropdownFilterItem)[],这就要求数组中的每个元素同时满足两种Item类型的要求——所以selectableTags类型的data因为缺少Icon字段而报错。
解决方案
可以通过类型映射+联合类型推导实现根据type字段自动匹配对应data结构的需求,具体步骤如下:
- 定义一个类型映射表,将每个过滤器类型与对应的Item类型绑定:
type FilterItemMap = { selectableTags: TSelectableTabsFilterItem; dropdown: TDropdownFilterItem; };
- 基于这个映射表生成
TFilter联合类型,让每个分支的type和data类型严格关联:
type TFilter = { [K in keyof FilterItemMap]: { type: K; label: TLocalesKey; data: FilterItemMap[K][]; }; }[keyof FilterItemMap];
这个写法会自动生成两个互斥的类型分支:
- 当
type为'selectableTags'时,data必须是TSelectableTabsFilterItem[] - 当
type为'dropdown'时,data必须是TDropdownFilterItem[]
完整修正代码
type TFiltersTypes = 'selectableTags' | 'dropdown'; type TLocalesKey = string; // 假设TLocalesKey是字符串类型,可根据实际定义调整 type TSelectableTabsFilterItem = { id: string; label: string; isSelected: boolean; }; type TDropdownFilterItem = { id: string; label: string; Icon: string; isSelected: boolean; }; // 新增类型映射表 type FilterItemMap = { selectableTags: TSelectableTabsFilterItem; dropdown: TDropdownFilterItem; }; // 重构TFilter为关联类型的联合 type TFilter = { [K in keyof FilterItemMap]: { type: K; label: TLocalesKey; data: FilterItemMap[K][]; }; }[keyof FilterItemMap]; type TFilterProps = { data: TFilter[]; }; const data = [ { type: 'selectableTags', label: 'filters.mediaType.label', data: [ { id: '1', label: '12', isSelected: true, }, { id: '2', label: '1', isSelected: false, }, { id: '3', label: '1', isSelected: false, }, ], }, { type: 'dropdown', label: 'filters.services.label', data: [ { id: '1', label: '1', Icon: '', isSelected: true, }, ], }, ] satisfies TFilter[]; // 现在不会报错
这样修改后,TypeScript会根据每个对象的type字段自动校验data的结构是否符合对应类型的要求,完全满足你需要的灵活关联效果。
内容的提问来源于stack exchange,提问作者John Dow
相关产品推荐
相关产品推荐

