Change msg to allow for stronger types
Closed this issue · 1 comments
jamesbirtles commented
At the moment it is not really possible to strongly type a msg without using type assertions. I had initially tried to get around this by adding the generic .get
function but this is ugly and is really just a type assertion in disguise. I realise now that redux already has this sorted, so we can pretty much just adopt that.
I'll demonstrate this with the counter example
enum Msg {
Increment,
Decrement,
SetCounter,
TrackInterval,
// ...
}
interface IncrementMessage {
kind: Msg.Increment;
}
interface DecrementMessage {
kind: Msg.Decrement;
}
interface SetCounterMessage {
kind: Msg.SetCounter;
value: number;
}
interface TrackIntervalMessage {
kind: Msg.TrackInterval;
value: number;
}
type CounterMessages =
| IncrementMessage
| DecrementMessage
| SetCounterMessage
| TrackIntervalMessage;
const Counter = component<Model, CounterMessages>({
update(msg, model) {
switch (msg.kind) {
case Msg.Increment:
return { ...model, counter: model.counter + 1 };
case Msg.Decrement:
return { ...model, counter: model.counter - 1 };
case Msg.SetCounter:
return { ...model, counter: msg.value };
case Msg.TrackInterval:
return { ...model, interval: msg.value };
}
return model;
},
});
jamesbirtles commented
Could probably even simplify this to
// Defined in fpreact somewhere
interface Message<K, V = undefined> {
kind: K;
value: V;
}
// In your component
type CounterMessages =
| Message<Msg.Increment>
| Message<Msg.Decrement>
| Message<Msg.SetCounter, number>
| Message<Msg.TrackInterval, number>;