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

如何在TypeScript中基于关联泛型Payload生成具体类实例?

TypeScript 基于Payload的kind字段创建对应Packet实例及后续处理器实现

我需要接收一个泛型Payload对象,根据它的kind字段创建对应具体类型的类实例,这应该可以用*关联类型(correlated types)*实现,但我还没掌握用法。因为要处理20多种kind类型,所以希望用映射方式实现,不想写一堆if...else和类型守卫。

测试代码

// 测试Payload(模拟从JSON解析后转为IPayload类型)
const alphaPayload = { kind: 'alpha', alpha: 'a' } as IPayload;
const betaPayload = { kind: 'beta', beta: 1 } as IPayload;

// 预期:alphaPacket和betaPacket分别为AlphaPacket和BetaPacket类型
const alphaPacket = PacketDecoder.decodePacket(alphaPayload);
const betaPacket = PacketDecoder2.decodePacket(betaPayload);

console.log(alphaPacket.getKind(), alphaPacket.getAlpha());
console.log(betaPacket.getKind(), betaPacket.getBeta());

已尝试的实现方式

// Payload定义
interface IPayload {
  kind: string;
}

interface AlphaPayload extends IPayload {
  kind: 'alpha';
  alpha: string;
}

interface BetaPayload extends IPayload {
  kind: 'beta';
  beta: number;
}

// Packet定义
interface IPacket {
  getPayload(): IPayload;
  getKind(): IPayload['kind'];
}

class Packet<T extends IPayload> implements IPacket {
  constructor(protected payload: T) {}

  getPayload(): T {
    return this.payload;
  }

  getKind(): T['kind'] {
    return this.payload.kind;
  }
}

class AlphaPacket extends Packet<AlphaPayload> {
  getAlpha(): string {
    return this.payload.alpha;
  }
}

class BetaPacket extends Packet<BetaPayload> {
  getBeta(): number {
    return this.payload.beta;
  }
}

// 类型映射
const kindToPacket = {
  alpha: AlphaPacket,
  beta: BetaPacket
} as const;

type KindMap = typeof kindToPacket;
type KindKey = keyof KindMap;
type KindToPacketConstructor<K extends KindKey = KindKey> = { [P in K]: KindMap[P] }[K]
type KindToPayload<K extends KindKey = KindKey> = { [P in K]: ConstructorParameters<KindMap[P]>[0] }[K]

// 类型守卫
function isValidKind(kind: string): kind is KindKey {
  return kind in kindToPacket;
}

function isValidPayload(payload: IPayload): payload is KindToPayload {
  return payload.kind in kindToPacket;
}

// 尝试实现1
class PacketDecoder {
  static decodePacket<T extends IPayload>(payload: T): Packet<T> {
    if (isValidKind(payload.kind)) {
      const PacketClass = kindToPacket[payload.kind];
      return new PacketClass(payload); // 此处类型不匹配,存在问题
    }

    throw new Error(`Unknown ${payload.kind}`);
  }
}

// 尝试实现2
class PacketDecoder2 {
  static decodePacket(payload: IPayload) {
    if (isValidPayload(payload)) {
      return PacketDecoder2.makePacket(payload.kind, payload);
    }

    throw new Error(`Unknown ${payload.kind}`);
  }

  static makePacket<K extends KindKey>(kind: K, payload: KindToPayload<K>) {
    const PacketClass: KindToPacketConstructor<K> = kindToPacket[kind];
    return new PacketClass(payload); // 此处类型推导存在问题
  }
}

后续需求

接下来我要定义一个PacketHandler类,希望它能接收decodePacket的结果,自动传递给对应的处理函数,比如handleAlpha(packet: AlphaPacket)和handleBeta(packet: BetaPacket)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:35:52