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

如何为Flow类创建基于Nodes的动态TypeScript Context类型?

解决方案

要实现让context仅允许节点id作为合法键、值类型匹配对应节点返回值的需求,我们可以利用TypeScript的泛型与映射类型来实现类型约束与自动推导:

1. 定义工具类型提取Context结构

先创建一个工具类型,从节点数组类型中自动推导context的键值对结构:

// 从节点数组类型中提取context的键值映射类型
type ContextFromNodes<Nodes extends Node<any>[]> = {
  [NodeType in Nodes[number] as NodeType['id']]: NodeType['result'];
};

这个类型会遍历数组中的每个节点,将节点的id作为键,result类型作为对应的值类型。

2. 修改Flow类为泛型类

将Flow改为泛型类,接收节点数组类型作为泛型参数,同时把context的类型绑定到上面的工具类型:

export class Node<T extends (...args: any[]) => any> {
  id: string;
  action: T;
  result: ReturnType<T>;

  constructor(id: string, action: T) {
    this.id = id;
    this.action = action;
  }
}

export class Flow<Nodes extends Node<(flow: Flow<Nodes>) => any>[]> {
  nodes: Nodes;
  context: ContextFromNodes<Nodes>;

  constructor(nodes: Nodes) {
    this.nodes = nodes;
    // 初始化context并执行节点动作填充值
    this.context = {} as ContextFromNodes<Nodes>;
    nodes.forEach(node => {
      const result = node.action(this);
      node.result = result; // 同步更新Node的result属性(可选)
      this.context[node.id as keyof ContextFromNodes<Nodes>] = result;
    });
  }
}

3. 验证效果

现在你的示例代码会完全符合预期:

const flow = new Flow([
  new Node("one", () => 1),
  new Node("two", (flow) => flow.context.one + 1),
]);

flow.context.one; // 类型为number,运行时值为1
flow.context.asdasd; // TypeScript报错:该类型不存在"asdasd"属性

关键说明

  • 泛型Nodes让TypeScript能精确推断传入节点数组中每个节点的id和返回值类型;
  • ContextFromNodes通过类型重映射,将节点数组转换为context的结构类型,实现键的合法性约束;
  • 构造函数中遍历节点并执行action,确保context在运行时被正确填充,同时类型层面严格匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:00:56