React Hook中如何根据传入type实现严格类型推断?
修复React Hook useFilterSelector的TypeScript类型推断问题
要解决这个类型推断问题,核心是让TypeScript明确传入的type参数与返回的过滤器类型之间的一一对应关系。下面提供两种可靠的解决方案:
基础类型定义
先明确过滤器类型和类型映射关系,这是后续方案的基础:
// 定义具体的过滤器类型 type ProductFilter = { type: 'product'; filterProducts: (ids: string[]) => void; }; type ContentFilter = { type: 'content'; filterContent: (tags: string[]) => void; }; // 建立字符串类型到过滤器类型的映射 type FilterTypeMap = { product: ProductFilter; content: ContentFilter; };
方案1:使用函数重载
函数重载可以直接为不同的输入参数指定对应的返回类型,TypeScript会自动匹配对应的重载规则,实现精准的类型推断:
// 重载声明:明确不同type对应的返回类型 function useFilterSelector(type: 'product'): ProductFilter; function useFilterSelector(type: 'content'): ContentFilter; // 函数实现:返回联合类型即可 function useFilterSelector(type: 'product' | 'content'): ProductFilter | ContentFilter { if (type === 'product') { return { type: 'product', filterProducts: (ids) => { /* 实际逻辑 */ } }; } else { return { type: 'content', filterContent: (tags) => { /* 实际逻辑 */ } }; } } // 调用时类型推断完全正确 const productFilter = useFilterSelector('product'); productFilter.filterProducts(['prod-1', 'prod-2']); // 无类型错误 const contentFilter = useFilterSelector('content'); contentFilter.filterContent(['news', 'tech']); // 无类型错误
方案2:泛型 + 类型映射
通过泛型约束type参数为FilterTypeMap的键,直接返回映射对应的类型,让TypeScript根据传入的具体type值推断返回类型:
function useFilterSelector<T extends keyof FilterTypeMap>(type: T): FilterTypeMap[T] { // 这里需要类型断言,因为TypeScript无法在分支中自动推断T的具体值 if (type === 'product') { return { type: 'product', filterProducts: (ids) => { /* 实际逻辑 */ } } as FilterTypeMap[T]; } else { return { type: 'content', filterContent: (tags) => { /* 实际逻辑 */ } } as FilterTypeMap[T]; } } // 类型推断效果与重载一致 const productFilter = useFilterSelector('product'); // 类型为ProductFilter const contentFilter = useFilterSelector('content'); // 类型为ContentFilter
为什么原条件类型会得到unknown?
你之前尝试的条件类型失效,大概率是因为:
- 函数参数的type没有被约束为具体的字面量类型,导致条件类型无法精准匹配分支
- 在函数实现中,TypeScript无法将分支返回值与条件类型的结果关联起来,最终导致类型收窄失败,退化为unknown或联合类型
上述两种方案都通过明确参数与返回值的类型绑定,解决了这个问题。
内容的提问来源于stack exchange,提问作者sooohka
相关产品推荐
相关产品推荐

