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

TypeScript中如何定义关联同对象内其他属性键的接口或类型?

TypeScript中约束对象属性键为另一属性键的子集

需求说明

需要定义Graph类型,让connections的键必须是nodes属性键的子集,当connections使用nodes中不存在的键时,TypeScript能抛出错误。基础的Node和Connection接口如下:

interface Node {
  id: string;
  // ...其他无关属性
}

interface Connection {
  fromNode: string;
  toNode: string;
  // ...其他无关属性
}

原有的Graph接口无法实现该约束:

interface Graph {
  nodes: Record<string, Node>
  connections: Record<string, Connection>
  // 其他无关属性
}

解决方案

要实现这种同一对象内属性键的依赖约束,不能用普通接口,需要借助泛型类型来捕获nodes的具体键集合,然后约束connections的键只能是这个集合的子集。

泛型Graph类型定义

type Graph<NodeKey extends string> = {
  nodes: Record<NodeKey, Node>;
  connections: Partial<Record<NodeKey, Connection>>;
  // 其他无关属性可以在这里添加
};

使用示例

当创建具体的Graph对象时,TypeScript会自动推断NodeKey的类型,从而约束connections的键:

// 正确示例:connections的键都是nodes的键子集
const validGraph: Graph<"nodeA" | "nodeB"> = {
  nodes: {
    "nodeA": { id: "nodeA" },
    "nodeB": { id: "nodeB" }
  },
  connections: {
    "nodeA": { fromNode: "nodeA", toNode: "nodeB" }
  }
};

// 错误示例:connections使用了nodes中不存在的"nodeC",TypeScript会报错
const invalidGraph: Graph<"nodeA" | "nodeB"> = {
  nodes: {
    "nodeA": { id: "nodeA" },
    "nodeB": { id: "nodeB" }
  },
  connections: {
    "nodeC": { fromNode: "nodeA", toNode: "nodeB" } // 此处会报错:类型“"nodeC"”的属性不能赋给类型“"nodeA" | "nodeB"”的索引类型
  }
};

自动推断泛型参数

如果不想手动指定NodeKey,可以创建一个辅助函数让TypeScript自动推断:

function createGraph<NodeKey extends string>(graph: Graph<NodeKey>) {
  return graph;
}

// 自动推断NodeKey为"nodeA" | "nodeB"
const autoGraph = createGraph({
  nodes: {
    "nodeA": { id: "nodeA" },
    "nodeB": { id: "nodeB" }
  },
  connections: {
    "nodeA": { fromNode: "nodeA", toNode: "nodeB" }
  }
});

// 错误示例:connections使用"nodeC"会报错
const autoInvalidGraph = createGraph({
  nodes: {
    "nodeA": { id: "nodeA" },
    "nodeB": { id: "nodeB" }
  },
  connections: {
    "nodeC": { fromNode: "nodeA", toNode: "nodeB" } // 报错
  }
});

补充说明

  • 使用Partial<Record<NodeKey, Connection>>是为了允许connections只包含nodes键的一部分,如果你要求connections必须包含所有nodes的键,可以去掉Partial,直接用Record<NodeKey, Connection>。
  • 这种方式完美适配运行时生成的UUID场景,只要创建对象时TypeScript能捕获到nodes的键集合,就能自动完成约束。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 07:08:10