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

TypeScript中Object.hasOwn与hasOwnProperty无法按预期收窄类型

解决TypeScript中hasOwnProperty/hasOwn无法收窄键类型的问题

问题分析

Object.entries()返回的键类型是string,而TypeScript默认的hasOwnProperty()和Object.hasOwn()的类型定义并没有将string收窄为目标对象的具体键类型(比如示例中的ExampleKeys),这是因为这些方法的类型签名未关联到具体对象的键集合。

通用解决方案:自定义类型守卫

可以编写一个自定义类型守卫函数,专门判断键是否属于目标对象的键类型,让TypeScript正确收窄类型:

type Example = {
    foo: string;
    bar: string;
}

type ExampleKeys = keyof Example;

const translation: Readonly<{[key in ExampleKeys]: string}> = {
    foo: "oof",
    bar: "rab",
};

// 自定义类型守卫函数
function isKeyOf<T extends object>(obj: T, key: PropertyKey): key is keyof T {
    return Object.hasOwn(obj, key);
}

function test(example: Example) {
    for (const [key, _] of Object.entries(example)) {
        if (isKeyOf(translation, key)) {
            // 此处key的类型已被收窄为ExampleKeys
            console.log(translation[key]); // 类型安全,无报错
        }
    }
}

原理说明

自定义类型守卫通过key is keyof T的返回类型断言,告知TypeScript:当函数返回true时,传入的key必然是T类型对象的键类型。这样在if分支内部,TypeScript能准确识别key的具体类型,既避免了类型断言,又保证了类型安全。

额外优化:直接遍历已知键集合

如果无需处理example的额外属性,也可以直接遍历目标键集合,从根源规避类型问题:

function test(example: Example) {
    // 直接遍历已知的键类型集合
    (Object.keys(translation) as ExampleKeys[]).forEach(key => {
        if (Object.hasOwn(example, key)) {
            console.log(example[key], translation[key]);
        }
    });
}

这种方式更直接,适合只需要处理目标键的场景。

内容的提问来源于stack exchange,提问作者yotamN

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:33:18