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

TypeScript类多态实现createPiece工厂函数类型值报错问题

问题根因

你遇到的报错本质是混淆了TypeScript的类型空间和值空间:

  • 你定义的pieces是interface接口,属于纯类型代码,编译阶段完成校验后会被完全擦除,不会生成任何运行时代码
  • 你在函数逻辑里写pieces[pieceName]是在运行时访问变量,此时pieces根本不存在,因此TS直接抛出错误。
    另外你的代码里存在拼写问题:骑士棋子的正确拼写是knight,你写成了knigth,建议先修正避免后续类型和实现不匹配。
正确实现

你需要单独创建一个运行时可用的类构造器映射对象,和类型定义一一对应,工厂函数从该映射中取出对应类做实例化即可。完整实现代码如下:

// 基类与初始化参数类型,可根据实际业务逻辑扩展
class piece {
  constructor(options?: pieceInit) {}
}
interface pieceInit {
  color?: "white" | "black";
  position?: [x: number, y: number];
}

// 各棋子子类
class pawn extends piece {}
class bishop extends piece {}
class rook extends piece {}
class king extends piece {}
class queen extends piece {}
// 修正拼写:knight 而非 knigth
class knight extends piece {}

// 类型空间:棋子名称到实例类型的映射
export interface Pieces {
  pawn: pawn;
  bishop: bishop;
  rook: rook;
  king: king;
  queen: queen;
  knight: knight;
}

// 值空间:棋子名称到对应类构造器的映射,用satisfies约束映射关系完全匹配类型定义
const pieceConstructorMap = {
  pawn,
  bishop,
  rook,
  king,
  queen,
  knight,
} satisfies Record<keyof Pieces, new (options?: pieceInit) => Pieces[keyof Pieces]>;

export function createPiece<K extends keyof Pieces>(
  pieceName: K,
  options?: pieceInit
): Pieces[K] {
  const TargetPiece = pieceConstructorMap[pieceName];
  return new TargetPiece(options) as Pieces[K];
}
效果验证

实现完成后,你预期的类型安全调用可以正常工作:

// 类型校验通过,运行时返回对应类实例
const piece1: pawn = createPiece("pawn");
const piece2: queen = createPiece("queen");

// 传入不存在的棋子名时,TS会直接报类型错误,拦截非法调用
// const invalidPiece = createPiece("knigth") // 报错:类型“"knigth"”的参数不能赋给类型“keyof Pieces”的参数
实现说明
  • 用satisfies约束pieceConstructorMap的键和Pieces的键完全一致,后续增删棋子类型时,TS会自动提示你补全映射关系,避免出现类型定义和运行时实现不一致的问题
  • 最后的as Pieces[K]是安全的类型断言:TS受静态分析能力限制,无法自动推导构造器返回值和泛型参数K的对应关系,而我们已经通过satisfies保证了映射关系的正确性,该断言不会引入类型风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 04:27:20