TypeScript如何为数组对象支持多泛型类型并保留字段校验?
多次级对象类型的ListItemComponent类型改造方案
核心做法是用TypeScript的联合类型和泛型约束,让items数组的每一项能独立指定次级对象类型,同时保留字段的严格类型校验。
第一步:定义基础类型结构
先把基础的抽象对象和两种Item的类型明确下来:
// 基础抽象父类 abstract class AbstractObj { /* 公共属性/方法 */ } // 对应主对象字段的Item(无次级obj) type MainItem<T extends AbstractObj> = { field: keyof T; // 必须是主对象T的键 label?: string; // 其他公共属性示例 } // 对应次级对象字段的Item(需指定自身obj和itemKey) type SubItem<SubObj extends AbstractObj> = { itemKey: string; // 标记次级对象的唯一标识 obj: SubObj; // 次级对象本身,必须继承AbstractObj field: keyof SubObj; // 必须是当前次级对象的键 label?: string; }
第二步:组合支持多类型的Items数组
通过联合类型把主对象Item和任意次级对象Item组合起来,同时用泛型约束主对象的类型:
// 组件Props类型,允许items数组混合主对象Item和任意次级对象Item type ListItemComponentProps<T extends AbstractObj> = { obj: T; // 主对象,继承AbstractObj items: Array<MainItem<T> | SubItem<AbstractObj>>; }
第三步:可选的严格类型校验优化
如果需要更精准的类型推断,避免AbstractObj的宽泛约束,可以用泛型数组来限定允许的次级对象类型:
// 更严格的Props类型,明确指定支持的次级对象类型集合 type StrictListItemComponentProps< T extends AbstractObj, SubItemTypes extends Array<SubItem<AbstractObj>> = [] > = { obj: T; items: Array<MainItem<T> | SubItemTypes[number]>; } // 使用示例 class User extends AbstractObj { id: number; name: string; } class Rdv extends AbstractObj { date: Date; location: string; } class Other extends AbstractObj { status: boolean; remark: string; } const props: StrictListItemComponentProps<User, [SubItem<Rdv>, SubItem<Other>]> = { obj: new User(), items: [ { field: 'name', label: '用户名' }, // 主对象字段,类型校验通过 { itemKey: 'rdv', obj: new Rdv(), field: 'date', label: '预约日期' }, // Rdv的字段,校验通过 { itemKey: 'other', obj: new Other(), field: 'status', label: '状态' } // Other的字段,校验通过 ] };
关键要点
- 联合类型让数组项可以灵活切换主对象或任意次级对象类型,符合规则要求。
- 泛型约束
SubObj extends AbstractObj确保所有次级对象都遵循基础抽象类的规范。 - 严格模式通过泛型数组明确指定允许的次级对象类型,进一步提升类型校验的准确性,避免非法字段传入。
内容的提问来源于stack exchange,提问作者banana
相关产品推荐
相关产品推荐

