让我们创造一个情境。有一个简单的抽象类定义棋盘游戏中的棋子,例如国际象棋或跳棋。
export abstract class Piece<Tags, Move, Position = Vector2> {
public constructor(public position: Position, public tags = null) {}
public abstract getMoves(board: Board<Tags, Move, Position>): Move[]
}
Board
也是一个抽象类。
export abstract class Board<Tags, Move, Position = Vector2> {
public constructor(
public size: Position,
public pieces: Piece<Tags, Move, Position>[]
) {}
}
当我尝试扩展这个类时,Typescript 说 board
方法中的 getMoves
是 any
。
class Checker extends Piece<Tags, Move> {
getMoves(board /*← any ?*/) {
return []
}
}
但是为什么呢?我对泛型或抽象类有什么误解吗?
答案 0 :(得分:0)
你必须声明一个与抽象类具有相同签名的方法,以证明你已经履行了抽象类的契约。
class Checker extends Piece<Tags, Move> {
public getMoves(board: Board<Tags, Move, Position>): Move[]{
return []
}
}
之后,您将能够创建一个 const piece:Piece = new Checker()
并能够依赖于对piece.getMoves(board) 调用的类型。
这个例子展示了基本模式(省略了你没有提供实现的类型)...
答案 1 :(得分:0)
这与泛型无关。
例如当你创建一个简单的函数并且不指定参数类型时,它是 any
function test(arg) {
// arg is of type any
}
另一个问题是打字稿根本没有为被覆盖的成员提供上下文输入。所以你必须在子类中再次列出所有参数和类型。
见Consider contextually typing class member functions by their base class/interface members #1373
答案 2 :(得分:0)
Typescript 支持 methods overloading。编译器无法推断参数的类型,因为您作为开发人员可以指定多个方法签名:
class Checker extends Piece<Tags, Move> {
getMoves():Move[];
getMoves(x: number):Move[];
getMoves(board: Board<Tags, Move, Position>):Move[];
getMoves(board: any):Move[] {
return [];
}
}
因此,您必须明确指定实现的方法签名。