如何修正TypeScript中hideQueryResult函数的属性隐藏失效问题?
问题:TypeScript中hideQueryResult函数类型错误修复
背景
useHider函数用于在TypeScript中隐藏对象指定属性并保证类型正确,调用后返回的对象无法访问被隐藏的属性(TypeScript会报错)。在此基础上封装的hideQueryResult函数,默认要隐藏createdAt、updatedAt、deletedAt三个属性,同时支持传入额外参数隐藏更多属性,但实际使用时类型校验不符合预期。
原实现代码:
const useHider = <T, K extends keyof T>(obj: T, keysToHide: K[]) => { let res = obj; keysToHide.forEach((key) => { delete res[key]; }); return res as Omit<T, K>; }; const hideQueryResult = <T, K extends keyof T>( query: T, keysToHide: K[] = [], ) => { const at = ["createdAt", "updatedAt", "deletedAt"] as K[]; const allKeysToHide = [...keysToHide, ...at]; const res = useHider(query, allKeysToHide); return res; };
问题现象
测试代码及不符合预期的结果:
const source = { id: "01ABC", title: "123", createdAt: "ABC", updatedAt: "ABC", deletedAt: "ABC", }; const res1 = useHider(source, ["createdAt", "updatedAt", "deletedAt"]); console.log(res1.id); // 正常(符合预期) console.log(res1.createdAt); // TypeScript报错(符合预期) const res2 = hideQueryResult(source); console.log(res2.id); // TypeScript报错(不符合预期:id应该是可访问的) const res3 = hideQueryResult(source, ["id"]); console.log(res3.createdAt); // 无报错(不符合预期:createdAt应该被隐藏)
问题原因
- 原
hideQueryResult的泛型定义中,将默认隐藏的时间戳键断言为K[],但K是用户传入的额外隐藏键的类型,当用户不传参数时K为空类型,导致类型断言不成立,进而返回的类型被错误推导。 - 返回类型没有正确合并默认隐藏键和用户传入的隐藏键,导致TypeScript无法正确识别哪些属性被隐藏。
修复方案
修改hideQueryResult的泛型逻辑,明确默认隐藏的键类型,并正确合并默认键与用户传入的键:
// 定义默认要隐藏的时间戳键类型 type TimestampKeys = 'createdAt' | 'updatedAt' | 'deletedAt'; const useHider = <T, K extends keyof T>(obj: T, keysToHide: K[]) => { let res = { ...obj }; // 创建对象副本,避免修改原对象(可选优化) keysToHide.forEach((key) => { delete res[key]; }); return res as Omit<T, K>; }; const hideQueryResult = <T, K extends keyof T = never>( query: T, keysToHide: K[] = [] ) => { // 提取query中存在的时间戳键,避免处理不存在的键 const defaultKeysToHide = ["createdAt", "updatedAt", "deletedAt"].filter( key => key in query ) as (TimestampKeys & keyof T)[]; // 合并默认键和用户传入的键 const allKeysToHide = [...defaultKeysToHide, ...keysToHide] as (TimestampKeys | K)[]; // 返回正确的类型:Omit<T, TimestampKeys | K> return useHider(query, allKeysToHide) as Omit<T, TimestampKeys | K>; };
修复说明
- 新增
TimestampKeys类型,明确默认隐藏的三个键,避免类型断言混乱。 - 为
hideQueryResult的泛型K设置默认值never,当用户不传额外隐藏键时,K为空类型,不影响默认隐藏逻辑。 - 过滤出
query中实际存在的时间戳键,避免尝试删除不存在的属性(可选优化,也可省略过滤直接使用原数组)。 - 明确返回类型为
Omit<T, TimestampKeys | K>,合并默认隐藏键和用户传入的键,让TypeScript正确识别被隐藏的属性。
验证效果
const res2 = hideQueryResult(source); console.log(res2.id); // 正常(符合预期) console.log(res2.createdAt); // TypeScript报错(符合预期) const res3 = hideQueryResult(source, ["id"]); console.log(res3.id); // TypeScript报错(符合预期) console.log(res3.createdAt); // TypeScript报错(符合预期)
内容的提问来源于stack exchange,提问作者Alpheus
相关产品推荐
相关产品推荐

