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

如何用TypeScript描述仅含字符串键的递归对象?

你尝试的代码写法有误,因为在类型定义中不能引用未完全定义的类型的键,且条件判断的位置不对。要实现“每一层嵌套都只有string类型键”的对象类型,可以通过递归结合联合类型来完成,同时也可以实现你提到的“非对象类型”(Not)。

步骤1:定义“非对象类型”

TypeScript中可以通过Exclude工具类型实现“排除object类型后的所有类型”,也就是你要的Not<object>:

// 排除所有object类型,得到原始类型、null、undefined等非对象类型
type NotObject = Exclude<unknown, object>;

注:object类型在TypeScript中包含普通对象、数组、函数、Set/Map等引用类型,NotObject会包含string、number、boolean、null、undefined、bigint、symbol这些类型。如果需要排除null/undefined,可以调整为:

type NotObject = Exclude<unknown, object | null | undefined>;

步骤2:定义递归的string键对象类型

基于NotObject,我们可以定义递归类型,要求每一层的键都是string,值要么是非对象类型,要么是符合同样规则的递归对象:

type RecursiveStringKeyObject = {
  [key: string]: NotObject | RecursiveStringKeyObject;
};

也可以用Record工具类型简化写法:

type RecursiveStringKeyObject = Record<string, NotObject | RecursiveStringKeyObject>;

验证效果

  • 符合要求的对象(仅string键,嵌套对象也遵循规则):
const validData: RecursiveStringKeyObject = {
  username: "zhangsan",
  age: 28,
  profile: {
    email: "zhangsan@example.com",
    address: {
      city: "Beijing",
      zip: 100000
    }
  }
};
  • 不符合要求的对象(包含symbol键)会被TypeScript报错:
const testSymbol = Symbol("id");
const invalidData: RecursiveStringKeyObject = {
  [testSymbol]: "123" // 类型错误:symbol类型的键不符合string键要求
};

补充:如果需要允许数组/函数等引用类型作为叶子节点

上面的NotObject排除了所有object类型,所以数组、函数等会被视为不合法的类型。如果需要允许这些类型作为叶子节点(仅普通对象需要递归遵循string键规则),可以调整递归逻辑:

// 递归类型:普通对象则递归应用规则,允许数组、函数等作为叶子节点
type RecursiveStringKeyObject = {
  [key: string]: 
    | Exclude<unknown, object>
    | Array<any>
    | Function
    | Set<any>
    | Map<any>
    | RecursiveStringKeyObject;
};

内容的提问来源于stack exchange,提问作者shau-kote

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:31:06