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

如何在TypeScript中定义完全未知结构的JSON字段类型?

解决TypeScript中任意JSON结构的类型定义问题

你遇到的这个问题很典型——当后端返回的字段是无固定结构的合法JSON时,{}确实不是合适的类型选择,TypeScript的提示也很明确:{}实际上代表任何非null/undefined的值,这完全不符合你需要的“任意JSON结构”的语义。下面给你几种靠谱的解决方案,按需选择:

1. 最灵活但需要类型守卫:unknown 类型

如果只需要接收任意合法JSON,不需要在编译期做太多类型检查,直接用unknown是最简单的选择:

type MyModel = {
  id: string;
  name: string;
  metadata: unknown;
};

优点:写法简单,完全兼容所有合法JSON值(包括对象、数组、原始类型)。
缺点:使用metadata时必须先通过类型守卫(比如typeof、instanceof)或者类型断言来缩小类型范围,否则无法访问其属性。

2. 严格匹配JSON结构:递归定义JSON类型

如果你想在编译期就严格限制metadata只能是合法的JSON值(即JSON支持的string/number/boolean/null/对象/数组),可以定义一个递归的类型:

// 定义所有合法的JSON值类型
type JSONValue = 
  | string
  | number
  | boolean
  | null
  | JSONValue[]
  | { [key: string]: JSONValue };

type MyModel = {
  id: string;
  name: string;
  metadata: JSONValue;
};

优点:完全贴合JSON的规范,编译期就能阻止非JSON类型的值(比如undefined、Symbol、函数等)被赋值给metadata。
缺点:如果后端返回的JSON里包含TypeScript不认为是合法JSON的特殊值(比如BigInt),这个类型会不兼容,但这种情况在标准JSON里很少见。

3. 仅接收JSON对象(不包含数组/原始类型):Record<string, unknown>

如果可以确定metadata一定是JSON对象(而不是数组或单个原始值),可以用Record<string, unknown>:

type MyModel = {
  id: string;
  name: string;
  metadata: Record<string, unknown>;
};

优点:比unknown更具体,至少明确是键值对结构,使用时不需要先判断是否为对象。
缺点:无法接收数组或单个原始类型的JSON值,适用范围较窄。

为什么{}不行?

再补充解释一下TypeScript里{}的语义:它表示“任何可以被赋值给空对象的值”,也就是除了null和undefined之外的所有值。比如你可以把"apple"、123甚至() => {}赋值给metadata: {},这显然和你需要的“任意JSON结构”完全不符,所以TypeScript会提示你不要使用这个类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 17:20:19