Skip to content

Instantly share code, notes, and snippets.

@DouglasLivingstone
Created October 15, 2015 09:00
Show Gist options
  • Save DouglasLivingstone/cdd89486617f7fdbe328 to your computer and use it in GitHub Desktop.
Save DouglasLivingstone/cdd89486617f7fdbe328 to your computer and use it in GitHub Desktop.
Type-checking Flux actions in TypeScript
interface ActionClass<T extends Action> {
prototype: T;
}
// Base class for actions
abstract class Action {
type: string;
constructor() {
// Copy from the prototype onto the instance
this.type = this.type;
}
}
// Decorator to set type names for action classes
function typeName(name: string) {
return function<T extends Action>(actionClass: ActionClass<T>) {
actionClass.prototype.type = name;
}
}
// Type guard for type checking
function isType<T extends Action>(action: Action, actionClass: ActionClass<T>): action is T {
return action.type == actionClass.prototype.type;
}
// Actions have nominal types
type NominalType = void;
// Two sample actions:
@typeName("RemoveAppointment")
class RemoveAppointment extends Action {
private _brand: NominalType;
constructor(public appointmentId: number) {
super();
}
}
@typeName("RescheduleAppointment")
class RescheduleAppointment extends Action {
private _brand: NominalType;
constructor(public appointmentId: number, public date: Date) {
super();
}
}
// Example compile errors:
function doRemove(action: RemoveAppointment) {
// ...
}
var action = new RescheduleAppointment(2553, new Date(2015, 10, 15));
doRemove(action); // Compile error!
function handleAction(action: Action) {
if (isType(action, RemoveAppointment)) {
action.date; // Compile error!
}
}
@techird
Copy link

techird commented Jan 20, 2016

I appreciate this approach very much! However, the redux document has a restriction on actions:

Actions are plain JavaScript objects

And the redux runtime do check actions before it dispatch. So an action with a constructor will raise an error.

Any idea to solve this?

@igorbt
Copy link

igorbt commented Mar 3, 2016

@techird have a look at this thread comment: reduxjs/redux#992 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment