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

TypeScript递归JSONValue类型定义后使用报错,求技术解答

TypeScript递归JSONValue类型属性访问报错问题分析

问题场景

定义了带递归逻辑的JSONValue类型,初始化对象时编译器无报错,但访问对象属性时提示Property 'someString' does not exist on type '{}',函数接收该类型参数访问属性也会报错。

示例代码:

type JSONPrimitive = {} | null | undefined // any primitive, null or undefined
type JSONObject = { [k: string]: JSONValue }
type JSONArray = JSONValue[]
type JSONValue = JSONArray | JSONObject | JSONPrimitive

let myObject: JSONValue = {
  someString: 'it complains',
  someObj: {
    anotherString: 'why?'
  },
  someNull: null
}

console.log( myObject.someString )
                      // ^ Error here `Property 'someString' does not exist on type '{}`

函数中访问属性的报错场景:

logMyObjectNested(myObject)
// This is totally fine...

function logMyObjectNested( objParam: JSONValue ) {
  console.log( objParam.someObj )
                        // ^ it complains ...
}

错误原因

核心问题出在JSONPrimitive的定义上:你把{}当作原始类型的一部分,但{}在TypeScript里代表无任何属性的空对象类型,同时它是几乎所有对象类型的父类型——任何对象都能赋值给{},但{}不能赋值给有具体属性的对象类型。

当JSONValue包含JSONPrimitive(带{})时,TypeScript会优先把你的{someString: ...}这类对象匹配到{}类型,而非JSONObject。因为{}的匹配优先级更高,这就导致访问属性时,编译器认为当前值可能是没有任何属性的{},所以抛出错误。

修复方案

修正JSONPrimitive的定义,去掉{},换成JSON标准的原始类型(string、number、boolean),空对象属于JSONObject范畴,不该放到原始类型里。

修正后的代码

// 符合JSON标准的原始类型定义
type JSONPrimitive = string | number | boolean | null | undefined
type JSONObject = { [k: string]: JSONValue }
type JSONArray = JSONValue[]
type JSONValue = JSONArray | JSONObject | JSONPrimitive

let myObject: JSONValue = {
  someString: 'it complains',
  someObj: {
    anotherString: 'why?'
  },
  someNull: null
}

// 注意:直接访问仍需类型守卫,因为JSONValue可能是数组/原始类型
if (typeof myObject === 'object' && myObject !== null && !Array.isArray(myObject)) {
  console.log( myObject.someString ) // 类型守卫后可安全访问
}

function logMyObjectNested( objParam: JSONValue ) {
  // 先通过类型守卫确认是JSONObject类型
  if (typeof objParam === 'object' && objParam !== null && !Array.isArray(objParam)) {
    console.log( objParam.someObj )
  }
}

logMyObjectNested(myObject)

补充说明

  • 修正类型后,不能直接访问JSONValue的属性,因为它可能是数组、null或原始类型。必须通过类型守卫先确认当前值是JSONObject,才能安全访问属性。
  • 最初的错误是混淆了JSON原始类型和对象类型的边界,把空对象{}错误归类到原始类型中,导致类型匹配逻辑混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:07:32