TypeScript中基于Tag配置创建泛型类型约束的实现方案
解决方案
先明确基础类型定义(基于你描述的现有代码结构):
// 现有枚举与配置类型 enum Tag { STANDARD = 'standard', UV_RANGE = 'uvRange', TEMP_RANGE = 'tempRange', CUSTOM = 'custom' } enum DataType { NUMBER = 'number', TIME_RANGE = 'timeRange', STRING = 'string' } interface CommonTagDataConfig { dataType: DataType.NUMBER | DataType.STRING; defaultValue: number | string; } interface TimeRangeDataConfig { dataType: DataType.TIME_RANGE; range: [Date, Date]; } type TagDataConfig = CommonTagDataConfig | TimeRangeDataConfig; // 标签-配置映射表 const TagConfigurations: Record<Tag, TagDataConfig> = { [Tag.STANDARD]: { dataType: DataType.NUMBER, defaultValue: 0 }, [Tag.UV_RANGE]: { dataType: DataType.TIME_RANGE, range: [new Date(), new Date()] }, [Tag.TEMP_RANGE]: { dataType: DataType.TIME_RANGE, range: [new Date(), new Date()] }, [Tag.CUSTOM]: { dataType: DataType.STRING, defaultValue: '' } };
实现泛型约束类型
1. TagForConfig<T>:根据配置类型筛选标签
这个泛型会从TagConfigurations中提取所有对应配置类型为T的Tag枚举值:
type TagForConfig<T extends TagDataConfig> = { [K in keyof typeof TagConfigurations]: typeof TagConfigurations[K] extends T ? K : never; }[keyof typeof TagConfigurations];
2. TagForType<T>:根据DataType筛选标签
这个泛型会提取所有TagConfigurations中dataType字段匹配T的Tag枚举值:
type TagForType<T extends DataType> = { [K in keyof typeof TagConfigurations]: typeof TagConfigurations[K]['dataType'] extends T ? K : never; }[keyof typeof TagConfigurations];
在组件Props中使用约束
基于配置类型约束组件
interface TimeRangeTagProps { // 只允许传入对应TimeRangeDataConfig的Tag tag: TagForConfig<TimeRangeDataConfig>; } const TimeRangeTag = ({ tag }: TimeRangeTagProps) => { return <div>Time Range Tag: {tag}</div>; }; // 合法:UV_RANGE对应TimeRangeDataConfig <TimeRangeTag tag={Tag.UV_RANGE} /> // 类型报错:STANDARD对应CommonTagDataConfig,不符合约束 // <TimeRangeTag tag={Tag.STANDARD} />
基于DataType约束组件
interface TimeTypeTagProps { // 只允许传入dataType为TIME_RANGE的Tag tag: TagForType<DataType.TIME_RANGE>; } const TimeTypeTag = ({ tag }: TimeTypeTagProps) => { return <div>Time Type Tag: {tag}</div>; }; // 合法:TEMP_RANGE的dataType是TIME_RANGE <TimeTypeTag tag={Tag.TEMP_RANGE} /> // 类型报错:CUSTOM的dataType是STRING,不符合约束 // <TimeTypeTag tag={Tag.CUSTOM} />
原理说明
这两个泛型通过映射类型遍历TagConfigurations的所有键,用条件类型判断当前键对应的配置是否匹配目标类型,最后通过[keyof typeof TagConfigurations]将所有符合条件的键合并为联合类型。整个校验在编译期完成,完全替代了运行时类型守卫,避开了React Hooks对条件判断的限制。
内容的提问来源于stack exchange,提问作者ScreamZ
相关产品推荐
相关产品推荐

