Created
October 15, 2015 09:00
-
-
Save DouglasLivingstone/cdd89486617f7fdbe328 to your computer and use it in GitHub Desktop.
Type-checking Flux actions in TypeScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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! | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I appreciate this approach very much! However, the redux document has a restriction on actions:
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?