如何通过泛型便捷构建组合类型并降低维护成本?
解决方案
基础简化方案:统一维护联合类型
首先将所有IRegisterDemoType实现类型合并为一个单一的联合类型,再通过泛型自动生成组合类型,避免重复手动列举:
export interface IRegisterDemoType<TaskType extends string = string, TaskProps = unknown> { key: TaskType; props: TaskProps; } type Demo1 = IRegisterDemoType<'demo1', { value: string; another: number; }>; type Demo2 = IRegisterDemoType<'demo2', undefined>; // 统一维护所有Demo类型的联合类型,新增类型只需添加到这里 type AllDemoTypes = Demo1 | Demo2; interface StoreData<Type extends IRegisterDemoType> { storeKey: Type['key']; storeProps: Type['props']; } interface InstanceData<Type extends IRegisterDemoType> { instanceKey: Type['key']; instanceProps: Type['props']; } // 利用TypeScript的分布式泛型自动生成联合类型,无需手动逐个映射 type AllStoreData = StoreData<AllDemoTypes>; type AllInstanceData = InstanceData<AllDemoTypes>; function handleStore(data: AllStoreData) { switch (data.storeKey) { case 'demo1': { console.log(data.storeProps); // 类型依然正确窄化为{ value: string; another: number } break; } case 'demo2': { console.log(data.storeProps); // 类型为undefined break; } } } function handleInstance(data: AllInstanceData) { switch (data.instanceKey) { case 'demo1': { console.log(data.instanceProps); // 类型正确 break; } } }
核心原理:当泛型参数是联合类型时,TypeScript会自动触发分布式行为,将StoreData<Demo1 | Demo2>拆解为StoreData<Demo1> | StoreData<Demo2>,和手动编写的效果完全一致,但维护成本大幅降低——新增类型只需在AllDemoTypes里追加即可。
进阶方案:自动生成所有Demo类型
如果要进一步降低40+类型的维护成本,可以通过类型映射直接从一个配置对象生成所有IRegisterDemoType实现,彻底告别手动定义Demo1、Demo2这类重复类型:
export interface IRegisterDemoType<TaskType extends string = string, TaskProps = unknown> { key: TaskType; props: TaskProps; } // 仅需维护这个映射表:key对应任务标识,值对应props类型 type DemoTypeMap = { demo1: { value: string; another: number }; demo2: undefined; // 新增任务直接在这里添加键值对即可 demo3: { id: number; name: string }; }; // 自动生成所有IRegisterDemoType的联合类型 type AllDemoTypes = { [K in keyof DemoTypeMap]: IRegisterDemoType<K, DemoTypeMap[K]>; }[keyof DemoTypeMap]; interface StoreData<Type extends IRegisterDemoType> { storeKey: Type['key']; storeProps: Type['props']; } interface InstanceData<Type extends IRegisterDemoType> { instanceKey: Type['key']; instanceProps: Type['props']; } // 自动生成组合类型 type AllStoreData = StoreData<AllDemoTypes>; type AllInstanceData = InstanceData<AllDemoTypes>; // 类型窄化依然正常工作 function handleStore(data: AllStoreData) { switch (data.storeKey) { case 'demo3': { console.log(data.storeProps.id); // 类型正确识别为number break; } } }
这个方案的优势是:所有类型定义都集中在DemoTypeMap中,新增或修改任务类型只需修改这一处,其余类型会自动同步更新,完全避免重复劳动。
内容的提问来源于stack exchange,提问作者Manda
相关产品推荐
相关产品推荐

