开启noUncheckedIndexedAccess后,如何定义无undefined的任意索引访问类型?
如何在开启
noUncheckedIndexedAccess时定义安全的任意键对象类型? 开启TypeScript的noUncheckedIndexedAccess选项后,带有字符串索引签名的对象,其属性访问的类型会变成「指定类型 + undefined」的联合类型——这符合大多数运行时场景,但如果你的对象(比如通过Proxy实现的兜底返回值的对象)能保证任意属性访问都不会返回undefined,可以用以下几种方法在保留该编译选项的前提下实现类型安全:
方法1:使用安全取值工具函数
创建一个泛型工具函数,通过类型断言确保返回值的类型不包含undefined,同时保留对键的类型约束:
function getSafeValue<T extends object, K extends keyof T>(obj: T, key: K): T[K] { // 断言基于你对运行时行为的保证:obj[key]一定存在 return obj[key] as T[K]; } // 定义你的索引类型 type ArbitraryStringIndexAccess = { [key: string]: number }; // 示例:用Proxy实现兜底返回值的对象 const object: ArbitraryStringIndexAccess = new Proxy({}, { get() { return 0; } }); // 安全取值,类型完全匹配 const value: number = getSafeValue(object, 'property');
方法2:自定义安全索引类型
通过类型工具创建一个绕过noUncheckedIndexedAccess的索引类型,将索引签名的类型还原为非可选的原始类型:
// 工具类型:移除索引签名的undefined联合类型 type SafeIndexType<T> = { [K in keyof T]: T[K]; } & { [key: string]: Exclude<T[string], undefined>; }; // 基于工具类型定义你的安全索引类型 type ArbitraryStringIndexAccess = SafeIndexType<{ [key: string]: number }>; const object: ArbitraryStringIndexAccess = new Proxy({}, { get() { return 0; } }); // 直接访问属性,类型为number而非number | undefined const value: number = object.property;
方法3:临时忽略类型检查(不推荐)
如果只是临时场景,可以用// @ts-ignore跳过单条语句的类型检查,但这种方式会失去TypeScript的类型保护,不建议在生产代码中大量使用:
const value: number = object.property; // @ts-ignore
注意事项
以上所有方法的前提是:你能保证运行时任意属性访问都不会返回undefined(比如Proxy兜底、对象预填充了所有可能的键)。如果运行时实际可能返回undefined,这些方法会导致类型不匹配的运行时错误。
另外,目前TypeScript官方尚未支持针对特定类型或属性单独关闭noUncheckedIndexedAccess的内置功能,相关议题「noUncheckedIndexAccess - 针对特定类型或属性禁用(使用场景:为每个属性返回值的动态Proxy)」关注度较低,暂时没有官方解决方案。
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

