如何定义TypeScript字典类型以确保任意字符串属性均非空?
解决TypeScript严格模式下动态属性访问的类型报错问题
问题背景
在开启strictNullChecks和noUncheckedIndexedAccess严格模式的TypeScript项目中,定义了如下索引类型:
type AlwaysHaveAnyProperties = { [prop in string]: { a: Something } }
当访问该类型的任意属性时,编译器抛出报错:
declare const dict: AlwaysHaveAnyProperties dict.someProp.a // Object is possibly 'undefined'.ts(2532)
由于项目启用了@typescript-eslint/no-non-null-assertion": "error"规则,无法使用非空断言dict.someProp!.a。实际场景为适配Proxy,需要让编译器认为任意字符串属性均存在有效值。
解决方案
方案1:使用类型断言函数
利用TypeScript的断言函数,明确告知编译器目标属性一定存在。这种方式符合eslint规则,且能保持类型安全:
// 针对Proxy场景,无需编写实际检查逻辑 function assertPropExists<T extends object, K extends string>( obj: T, key: K ): asserts obj is T & Record<K, { a: Something }> {} // 使用示例 assertPropExists(dict, 'someProp'); dict.someProp.a; // 编译器不再报错
方案2:调整类型定义为全属性覆盖映射类型
通过交叉类型结合映射类型,让TypeScript默认认为所有字符串键对应的属性都存在:
type AlwaysHaveAnyProperties = { [key: string]: { a: Something } } & { [K in string]: { a: Something } }; // 使用示例 declare const dict: AlwaysHaveAnyProperties; dict.someProp.a; // 编译器不再报错
方案3:Proxy实例直接类型断言
如果是直接声明Proxy实例,可在创建时直接断言类型(适配Proxy拦截所有属性访问的特性):
interface AlwaysHaveAnyProperties { [key: string]: { a: Something }; } // 创建Proxy时断言类型 const dict = new Proxy({}, { get(target, prop) { return { a: /* 实际的Something类型值 */ }; } }) as AlwaysHaveAnyProperties; dict.someProp.a; // 编译器不再报错
内容的提问来源于stack exchange,提问作者aleclofabbro
相关产品推荐
相关产品推荐

