如何在传入Iterable<Coords>时强制Grid泛型T=Tile?
解决方案
要实现“传入Iterable<Coords>时强制泛型T等于Tile”的约束,同时解决ts(2345)类型错误,可以通过重载签名的类型推断结合类型断言,或者补充静态工厂方法来处理,以下是具体实现:
修正基础代码错误
首先修复原代码中的两处基础问题:
Map<T>类型不合法,Map需要明确键和值类型,这里应改为Map<string, T>(用Tile的toString结果作为键)- 循环中
coord未定义,需将迭代变量赋值给coord
方法一:优化构造函数重载与类型断言
通过给类添加默认泛型,并在构造函数中使用类型断言确保类型匹配:
class Tile { constructor(public coord: Coords) {} toString() { return `${this.coord.x},${this.coord.y}`; } } type Coords = { x: number; y: number }; class Grid<T extends Tile = Tile> { tiles = new Map<string, T>(); setTile(tile: T) { this.tiles.set(tile.toString(), tile); } // 无参构造,T默认取Tile constructor(); // 传入Coords集合时,强制T为Tile constructor(coords: Iterable<Coords>); // 传入T类型的Tile集合 constructor(tiles: Iterable<T>); constructor(input?: Iterable<T> | Iterable<Coords>) { if (!input) return; for (const item of input) { if (item instanceof Tile) { this.setTile(item as T); } else { // 当传入Coords时,重载已确保T为Tile,类型断言安全 this.setTile(new Tile(item) as T); } } } }
原理说明
- 给
Grid类设置默认泛型T = Tile,无参构造或传入Coords集合时,TypeScript会自动推断T为Tile - 构造函数中的类型断言
as T是安全的:当迭代项是Coords时,重载签名已限定此时T必须是Tile,new Tile(item)的类型完全匹配
方法二:使用静态工厂方法(更清晰)
如果觉得构造函数重载的类型逻辑太复杂,可以补充静态方法专门处理Coords集合的情况,类型语义更明确:
class Grid<T extends Tile> { tiles = new Map<string, T>(); setTile(tile: T) { this.tiles.set(tile.toString(), tile); } constructor(); constructor(tiles: Iterable<T>); constructor(input?: Iterable<T>) { if (!input) return; for (const tile of input) { this.setTile(tile); } } // 专门从Coords集合创建Grid<Tile> static fromCoords(coords: Iterable<Coords>): Grid<Tile> { const grid = new Grid<Tile>(); for (const coord of coords) { grid.setTile(new Tile(coord)); } return grid; } } // 使用示例 const coords = [{x: 1, y: 2}, {x: 3, y: 4}]; const gridFromCoords = Grid.fromCoords(coords); // 类型为Grid<Tile>
优势
- 静态方法
fromCoords明确返回Grid<Tile>,无需依赖构造函数的重载推断,类型更直观 - 构造函数逻辑简化,只处理
Tile集合的情况,降低类型复杂度
内容的提问来源于stack exchange,提问作者ChrisOram
相关产品推荐
相关产品推荐

