索引签名导致测试失败,TypeScript代码问题求助
嘿,我来帮你拆解这个问题!先看你贴的代码片段,首先注意到一个很容易踩的坑——你在recieveAttack方法里重新声明了一个局部的ships变量,这大概率是测试失败的核心原因之一。咱们一步步来分析:
1. 局部变量遮蔽了外部依赖
你在方法内部写了:
const ships: { [key: string]: Ship } = {};
如果你的类原本有一个实例属性ships(比如用来存储游戏里的所有船只),这个局部声明会直接“覆盖”外部的属性——也就是说,你在方法里操作的是一个全新的空对象,而不是测试中预期的、已经初始化好的船只集合。测试代码肯定找不到预期的船只,断言自然会失败。
解决办法:
删掉这个局部的ships声明,直接用类的实例属性,比如this.ships来访问(前提是你的类里已经定义了这个属性)。
2. 索引签名的类型严谨性问题
你的索引签名{ [key: string]: Ship }定义的是“所有字符串键对应的都是非空的Ship实例”,但初始化的空对象其实并不符合这个类型——因为空对象里任何键对应的都是undefined。如果你的测试用的是严格模式的TypeScript检查,这种类型不匹配会导致测试运行时抛出错误。
解决办法:
把索引签名改成可选值的形式,更符合实际情况:
// 允许键对应的值是Ship或者undefined const ships: { [key: string]: Ship | undefined } = {};
如果是类属性的话,同样调整类型即可。
3. 测试逻辑的依赖缺失
如果你的测试是验证攻击逻辑(比如攻击某个船只后标记受损),那局部的空ships对象会导致方法找不到目标船只。比如你通过data-ship-type拿到船型后,ships[target]会是undefined,后续的攻击逻辑无法执行,测试断言就会失败。
解决办法:
- 如果是用类属性
ships,在测试初始化时给ships添加测试需要的船只条目; - 要是必须用局部变量,那在测试运行前要先给这个局部
ships填充测试数据(不过更推荐用类属性,方便测试控制依赖)。
修正后的代码示例
假设你的类原本应该有实例属性ships,修正后的代码大概是这样:
class BattleShipGame { // 调整索引签名为可选值,更严谨 private ships: { [key: string]: Ship | undefined } = {}; recieveAttack(e: Event) { let target: string | null; const location = document.getElementById(e.target.id as string); // 去掉局部ships声明,使用实例属性 console.log(location?.hasChildNodes()); if (location?.hasChildNodes()) { target = (e.currentTarget as HTMLElement).children[0].getAttribute('data-ship-type'); if (target && this.ships[target]) { // 处理攻击逻辑,比如标记船只受损 this.ships[target].takeDamage(); } } console.log(location?.classList.contains('occupied')); } }
内容的提问来源于stack exchange,提问作者user3799793

