You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修正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应该被隐藏)

问题原因

  1. 原hideQueryResult的泛型定义中,将默认隐藏的时间戳键断言为K[],但K是用户传入的额外隐藏键的类型,当用户不传参数时K为空类型,导致类型断言不成立,进而返回的类型被错误推导。
  2. 返回类型没有正确合并默认隐藏键和用户传入的隐藏键,导致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>;
};

修复说明

  1. 新增TimestampKeys类型,明确默认隐藏的三个键,避免类型断言混乱。
  2. 为hideQueryResult的泛型K设置默认值never,当用户不传额外隐藏键时,K为空类型,不影响默认隐藏逻辑。
  3. 过滤出query中实际存在的时间戳键,避免尝试删除不存在的属性(可选优化,也可省略过滤直接使用原数组)。
  4. 明确返回类型为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 16:57:41