上下文:我想開發一個模式,使用TypeState庫在打字稿中創建可擴展狀態機。 TypeState爲Typescript提供了一個類型安全的狀態機,雖然不是問題的核心,但它有助於說明我的目標。創建可擴展枚舉用於可擴展接口
問題:我遇到了在打字稿擴展enum
和interface
和class
聲明實現它們創造一個可擴展的模式問題。
目標:下面的psuedocode說明了我想讓我的模式看起來像什麼。
1)定義基enum States
2)擴展enum States
與附加狀態導致enum ExtendedStates
2)使用States
定義ParentInterface
和輸入狀態機
3)經由ChildInterface
擴展ParentInterface
並重寫States
與ExtendedStates
4)實施ParentInterface
在class Parent
5)擴展class Parent
在class Child
實施ChildInterface
6)能夠調用broadcastState()
從任一類,並獲得當前的狀態。
我已經在其他語言中使用了這種模式,對於理解Typescript的侷限性和任何可以實現相同目標的替代模式我都會很感激。
import {TypeState} from "typestate";
enum States {
InitialState
}
// extends is not available on enum, looking for alternative
enum ExtendedStates extends States {
AdditionalState
}
/////////////////////////////////////////
// this works fine
interface ParentInterface {
fsm: TypeState.FiniteStateMachine<States>;
states: typeof States;
message: string;
}
// incorrectly extends ParentInterface, types of fsm/states are incompatible
interface ChildInterface extends ParentInterface {
fsm: TypeState.FiniteStateMachine<ExtendedStates>;
states: typeof ExtendedStates;
}
/////////////////////////////////////////
class Parent implements ParentInterface {
public fsm: TypeState.FiniteStateMachine<States>;
public states: typeof States;
public message: string = "The current state is: ";
constructor(state: States | undefined) {
state = state ? state : this.states.InitialState;
this.fsm = new TypeState.FiniteStateMachine(state);
this.broadcastCurrentState();
}
public broadcastCurrentState(): void {
console.log(this.message + this.fsm.currentState);
}
}
class Child extends Parent implements ChildInterface {
public fsm: TypeState.FiniteStateMachine<ExtendedStates>;
public states: typeof ExtendedStates;
constructor(state: ExtendedStates | undefined) {
state = state ? state : this.states.InitialState;
this.fsm = new TypeState.FiniteStateMachine(ExtendedStates);
this.broadcastCurrentState();
}
}
最近我已經得到
import {TypeState} from "typestate";
enum States {
InitialState
}
enum ExtendedStates {
InitialState,
ExtendedState
}
class Parent {
public fsm: TypeState.FiniteStateMachine<States>;
public states: typeof States;
public message: string = "The current state is: ";
// T is declared but never used
constructor(state: <T> | undefined) {
state = state ? state : this.states.InitialState;
// cannot find name T
this.fsm = new TypeState.FiniteStateMachine<T>(state);
this.broadcastCurrentState();
}
public broadcastCurrentState(): void {
console.log(this.message + this.fsm.currentState);
}
}
// types of fsm are incompatible
class Child extends Parent {
public fsm: TypeState.FiniteStateMachine<ExtendedStates>;
public states: typeof ExtendedStates;
constructor(state: ExtendedStates | undefined) {
// Param not assignable to type <T>
super(state);
}
}
這種嘗試得到接近理想的結果,但在enum
很多重複的代碼不編譯和結果。它也失去了界面,這不是要求,但提供了一個很好的安全網。
我很想聽聽你們都說了些什麼。我覺得這是一種強大的模式,我錯過了一些簡單的事情來實現它。
偉大的答案,我認爲這將工作得很好。 – gjolund