-
-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add data to states #12
Comments
I'm currently working on a fork that can do something like that while keeping all the magical type checking. So far, the main differences are that you use a class instead of an enum class Elevator {
DoorsOpened = {a:1};
DoorsClosed = {b: 3};
Moving = "Henlo"
} of which an instance has to be passed to the constructor var fsm = new typestate.FiniteStateMachine(new Elevator(), "DoorsClosed"); and instead of writing fsm.from("DoorsOpened").to("DoorsClosed"); https://github.com/stefnotch/TypeState/blob/master/example/example.ts |
@stefnotch Cool! Open a PR, is there a way to preserve the existing behavior with to avoid a breaking change? |
I think it should be possible to make the existing There is another breaking change as well. The callback now have an optional second parameter which is the current context. public on<U extends keyof T>(state: U, callback: (from?: keyof T, context?: T[U], event?: any) => any): This could be fixed by making the |
@stefnotch I see, typescript enums are certainly cumbersome. I need some more time to think about this, given the length of time TypeState has relied on enums for defining states I want to be careful about how to proceed. A couple options I see right now:
public withData<U extends keyof T>(state: U, cb: (data: T[U]) => any): FiniteStateMachine<T> {
...
}
|
I looked into this a bit more. I have found a type that sort of works for classes and enums. enum Swag {
Yo,
Yolo,
Nope
}
var x: keyof typeof Swag;
x = "Yolo";
class SwagClass {
static "Yo": { hello: 1 };
}
var y: keyof typeof SwagClass;
y = "Yo"; I also looked into associating a context with an enum in a typesafe way. However, the approach I found isn't quite as pretty as I'd like enum Swag {
Yo,
Yolo,
Nope
}
const SwagContext = {
[Swag.Yo]: { hello: 1 },
[Swag.Yolo]: "x",
[Swag.Nope]: null
};
// Now the user is forced to specify something for `K`
class FiniteStateMachine<T, K> {
context: K;
constructor(startState: T, context?: K) {
this.context = context;
}
}
var fsm = new FiniteStateMachine<Swag, typeof SwagContext>(
Swag.Yolo,
SwagContext
);
// It works with type checking
fsm.context[Swag.Yo]; |
Regarding the sufficient type description, it might be possible to use conditional types to cover both cases (enums and classes). Here is an example of conditional types. type ConditionalTest<T> = T extends object ? number : string;
enum Swag {
Yo,
Yolo,
Nope
}
let y: ConditionalTest<Swag>; // string
class SwagClass {}
let x: ConditionalTest<SwagClass>; // number |
This is more of a question/feature request (or at least basis for discussion of such):
Is there any standard way to add data to a state, or would you be interested in discussing such a feature?
I think in many business cases it would be useful to attach some data to a state as opposed to creating a multitude of individual states (which not practical if there are many "sub-states").
Sadly TypeScript does not support data in enum cases, so I don't see a straightforward way yet to implement this in TypeScript/TypeState. In Swift or Rust it is a core feature to add data to enum cases, so under such circumstances no special casing would be needed.
An example of a state machine that would be more useful with added data would be:
Do you have any implementation hints on how to approach something like the above? Or is this something that should not attempted when working with FSMs for some reason?
The text was updated successfully, but these errors were encountered: