如何为动态嵌套对象强类型定义?规避TypeScript any与类型报错
解决动态嵌套对象的TypeScript类型报错问题
我们的代码检查规则禁止使用any类型,尝试为动态嵌套对象实现强类型定义时遇到如下问题:
示例代码
type FlexibleValueType = { [key: string]: string | FlexibleValueType } export const alphabeticalSortEntries = (a: FlexibleValueType, b: FlexibleValueType) => { return a.fields.internal?.default.localeCompare(b.fields.internal?.default) }
报错信息
Property 'internal' does not exist on type 'string | FlexibleValueType'. Property 'internal' does not exist on type 'string'
问题原因
FlexibleValueType的索引签名定义了属性值可以是string或自身类型,TypeScript无法确定a.fields到底是字符串还是嵌套对象,因此不允许直接访问internal属性。
解决方案
方法一:使用类型守卫(Type Guard)
通过类型守卫在运行时判断属性值的类型,确保安全访问嵌套属性:
- 定义类型守卫函数:
function isFlexibleValue(obj: string | FlexibleValueType): obj is FlexibleValueType { return typeof obj === 'object' && obj !== null; }
- 修改排序函数,先验证类型再访问:
export const alphabeticalSortEntries = (a: FlexibleValueType, b: FlexibleValueType) => { // 逐层验证类型,获取默认值,不存在则用空字符串兜底 const aDefault = isFlexibleValue(a.fields) && isFlexibleValue(a.fields.internal) ? a.fields.internal.default : ''; const bDefault = isFlexibleValue(b.fields) && isFlexibleValue(b.fields.internal) ? b.fields.internal.default : ''; return aDefault.localeCompare(bDefault); };
方法二:细化类型定义(适用于部分已知结构)
如果明确知道fields和internal大概率是嵌套对象而非字符串,可以细化类型定义,减少类型判断的复杂度:
type FlexibleValueType = { [key: string]: string | FlexibleValueType; // 明确fields和internal的可能结构 fields?: { internal?: { default: string; } & FlexibleValueType; }; };
注:即使细化了类型,由于索引签名的存在,fields仍可能被赋值为字符串,因此建议结合类型守卫使用,避免运行时错误。
内容的提问来源于stack exchange,提问作者San Jay Falcon
相关产品推荐
相关产品推荐

