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
相关产品推荐
相关产品推荐

