如何基于函数参数实现TypeScript对象值类型收窄?
解决方法
方法一:用函数重载实现精准类型推断
直接为不同的FilterName参数定义对应的返回类型,让TypeScript能自动匹配输入和输出的类型关系:
export enum FilterName { Date = 'date', State = 'state', } export enum FilterField { CreatedAtStartDate = 'createdAtStartDate', CreatedAtEndDate = 'createdAtEndDate', State = 'state', // 补全原代码缺失的逗号 } export type TDateFields = { min: FilterField.CreatedAtStartDate; max: FilterField.CreatedAtEndDate; }; // 先定义函数重载签名,明确不同参数对应的返回类型 export function getFilterField(filterName: FilterName.Date): TDateFields; export function getFilterField(filterName: FilterName.State): FilterField.State; // 再写函数实现 export function getFilterField(filterName: FilterName) { return ({ [FilterName.Date]: { min: FilterField.CreatedAtStartDate, max: FilterField.CreatedAtEndDate, }, [FilterName.State]: FilterField.State, }[filterName]); } // 调用时自动推断类型,无需断言 const dateFields = getFilterField(FilterName.Date); dateFields.min; // 无报错,类型正确 const stateField = getFilterField(FilterName.State); // stateField类型自动为FilterField.State
方法二:用泛型条件类型绑定输入输出
通过泛型参数关联输入的FilterName,再用条件类型返回对应结果,适合后续需要扩展更多过滤类型的场景:
export enum FilterName { Date = 'date', State = 'state', } export enum FilterField { CreatedAtStartDate = 'createdAtStartDate', CreatedAtEndDate = 'createdAtEndDate', State = 'state', } export type TDateFields = { min: FilterField.CreatedAtStartDate; max: FilterField.CreatedAtEndDate; }; // 定义映射类型,把FilterName和对应的返回类型绑定 type FilterReturnType<T extends FilterName> = T extends FilterName.Date ? TDateFields : FilterField.State; export const getFilterField = <T extends FilterName>(filterName: T): FilterReturnType<T> => { return ({ [FilterName.Date]: { min: FilterField.CreatedAtStartDate, max: FilterField.CreatedAtEndDate, }, [FilterName.State]: FilterField.State, }[filterName]) as FilterReturnType<T>; }; // 调用示例 const dateFields = getFilterField(FilterName.Date); dateFields.min; // 类型正确,无报错 const stateField = getFilterField(FilterName.State);
注意
原代码里的FilterField枚举中,CreatedAtEndDate字段后面缺失了逗号,需要补上才能正常编译。
两种方法都能让TypeScript根据传入的FilterName自动收窄返回类型,不需要手动添加类型断言。
内容的提问来源于stack exchange,提问作者paradox37
相关产品推荐
相关产品推荐

