TypeScript泛型推断问题:如何避免使用'as'类型断言?
TypeScript泛型DataTable过滤器的类型推断问题解决方案
问题背景
使用TypeScript泛型开发DataTable通用过滤器时,遇到类型推断问题:创建包含计算属性的对象时,TypeScript无法正确推断其类型为DocumentFilterState<FilterName>,必须使用as断言才能通过类型检查。
相关代码:
type DocumentFilterStateFilter<FilterName extends string> = `${FilterName}Filter`; type DocumentFilterState<FilterName extends string> = Record<DocumentFilterStateFilter<FilterName>, boolean>; function temporary<FilterName extends string>(filterName: FilterName): () => DocumentFilterState<FilterName> { const filterProperty: DocumentFilterStateFilter<FilterName> = `${filterName}Filter`; return (): DocumentFilterState<FilterName> => ({ [filterProperty]: true, }); }
报错信息:
Type '{ [x: string]: boolean; }' is not assignable to type 'DocumentFilterState
'.
解决方案
方案1:让TypeScript自动推断函数返回类型
去掉temporary函数的返回类型标注,TypeScript会自动推断返回的函数类型为() => DocumentFilterState<FilterName>,此时返回对象无需额外断言:
type DocumentFilterStateFilter<FilterName extends string> = `${FilterName}Filter`; type DocumentFilterState<FilterName extends string> = Record<DocumentFilterStateFilter<FilterName>, boolean>; function temporary<FilterName extends string>(filterName: FilterName) { const filterProperty = `${filterName}Filter` as DocumentFilterStateFilter<FilterName>; return () => ({ [filterProperty]: true, }); }
方案2:使用辅助函数封装对象创建逻辑
将对象创建逻辑封装到辅助函数中,把断言集中在辅助函数内部,业务代码中无需显式使用as:
type DocumentFilterStateFilter<FilterName extends string> = `${FilterName}Filter`; type DocumentFilterState<FilterName extends string> = Record<DocumentFilterStateFilter<FilterName>, boolean>; // 辅助函数:创建带指定键值对的对象 function createFilterState<K extends string>(key: K, value: boolean): Record<K, boolean> { return { [key]: value } as Record<K, boolean>; } function temporary<FilterName extends string>(filterName: FilterName): () => DocumentFilterState<FilterName> { const filterProperty = `${filterName}Filter` as DocumentFilterStateFilter<FilterName>; return () => createFilterState(filterProperty, true); }
说明
关于filterProperty的类型断言:由于TypeScript无法将泛型参数的模板字符串表达式自动推断为对应的模板字符串类型,这一步断言是必要的,但它是安全的——我们明确知道拼接后的字符串符合${FilterName}Filter的格式。
内容的提问来源于stack exchange,提问作者C. Leroy
相关产品推荐
相关产品推荐

