我不确定我是否在描述标题中当前的任务。我想问的来自以下要求。
我正在尝试为有限状态机的状态做一个抽象,并提出以下定义(在打字稿中)
interface IState {
send<T, E>(message: T, callback?:(event: E)=>void): IState;
}
我试图表达有限状态机的状态应该能够接受消息并返回新状态,并带有一个可选的回调来处理转换期间的事件。
当将此接口实现为具体状态时,会出现问题。
例如,我正在尝试制作一个只有两种状态的简单状态机,LEFT和RIGHT,并带有三个可能的消息go-on、turn-left、turn-right。下表显示了它们的关系。
关键是我想限制状态LEFT只接受go-on和turn-right消息,而 send turn-left to LEFT预计是编译错误。
我尝试在 typescript 3.4.5 中实现如下。
class Left implements IState {
send(m: 'go-on', cb?: (e: never) => void): Left;
send(m: 'turn-right', cb?: (e: never) => void): Right;
send(m: 'go-on' | 'turn-right', cb?: any) {
return m === 'go-on' ? new Left() : new Right();
}
}
class Right implements IState {
send(m: 'go-on', cb?: (e: never) => void): Right;
send(m: 'turn-left', cb?: (e: never) => void): Left;
send(m: 'go-on' | 'turn-left', cb?: any) {
return m === 'go-on' ? new Right() : new Left();
}
}
该实现没有编译错误,并且自动完成按预期工作。但是因为它看起来很奇怪,所以我问了一个问题TypeScript function generic can only work for function overload with more than one signatures。
感谢您在该问题下的友好回复,我了解将重载函数分配给泛型函数是错误的。但是,如何在保持特定状态只接受所需类型的消息的同时表达状态的一般接口呢?
我能想到的另一个抽象是
interface IState<T, E, R extends IState<?, ?, ?>> {
send(message: T, callback?:(event: E)=>void): R;
}
但是返回类型是递归的,我不知道上面那三个问号要填什么。
一个更简单的版本可能是
interface IState<T, E> {
send(message: T, callback?:(event: E)=>void): IState<any, any>;
}
除了返回类型中令人讨厌的any之外,它的行为似乎很像。
interface IState {
send<T, E>(message: T, callback?:(event: E)=>void): IState;
}
我在 GitHub 中发现了一个关于 generic value 的可能相关问题。
这个问题定义明确吗?
如果属实,上面列出的这些方法是否有正确的解决方案?
如果为假,正确的解决方案是什么?