开启exactOptionalPropertyTypes后Object.hasOwn的TS undefined错误原因
问题原因及解决方案
第一个错误(ts(18048):shape.radius可能为undefined)
开启exactOptionalPropertyTypes后,TypeScript对可选属性的语义做了严格限制:可选属性要么完全不存在,要么存在且值必须符合属性的非undefined类型(比如radius?: number等价于「无radius属性」或「有radius且值为number」)。但目前TypeScript的内置类型守卫(Object.hasOwn)没有和这个配置联动,即使检测到属性存在,TypeScript也无法自动将对象类型窄化为「包含该属性且值非undefined」的类型,所以仍然会提示可能为undefined。
解决办法
自定义一个类型守卫函数,明确告诉TypeScript检测到属性存在时的类型:
interface Shape { radius?: number; } function hasOwnProp<T extends object, K extends PropertyKey>(obj: T, key: K): obj is T & Record<K, Exclude<T[K], undefined>> { return Object.hasOwn(obj, key); } function getArea(shape: Shape) { if (hasOwnProp(shape, 'radius')) { // 这里shape.radius会被正确推断为number,不再提示undefined return Math.PI * shape.radius ** 2; } return 0; }
第二个错误(ts(2375):类型不兼容)
同样是exactOptionalPropertyTypes的严格限制导致的:当你定义radius?: number时,TypeScript不允许该属性存在且值为undefined——可选属性的语义是「可省略」,而非「存在时可以为undefined」。所以{ radius: undefined }不符合Shape的类型定义。
解决办法
如果业务场景确实需要属性存在但值可以为undefined,不要用可选属性语法,直接把属性类型定义为number | undefined(必须存在该属性):
interface Shape { radius: number | undefined; } // 现在可以正常创建该对象,不会报错 const s1: Shape = { radius: undefined };
如果不需要属性必须存在,那就不要给radius赋值undefined,直接省略该属性:
const s1: Shape = {}; // 符合类型定义
内容的提问来源于stack exchange,提问作者komote7665
相关产品推荐
相关产品推荐

