Redux has three major parts that should be typed:
Typing Redux state
Typing your state
object, works the same as typing any other object in Flow.
1
2
3
4
5
6
7
8
9
10
|
type State = {
users: Array<{
id: string,
name: string,
age: number,
phoneNumber: string,
}>,
activeUserID: string,
};
|
{"value":"type State = {\n users: Array<{\n id: string,\n name: string,\n age: number,\n phoneNumber: string,\n }>,\n activeUserID: string,\n // ...\n};\n","tokens":[{"type":"T_TYPE","context":"normal","value":"type","line":1,"start":0,"end":4},{"type":"T_IDENTIFIER","context":"type","value":"State","line":1,"start":5,"end":10},{"type":"T_ASSIGN","context":"type","value":"=","line":1,"start":11,"end":12},{"type":"T_LCURLY","context":"type","value":"{","line":1,"start":13,"end":14},{"type":"T_IDENTIFIER","context":"normal","value":"users","line":2,"start":17,"end":22},{"type":"T_COLON","context":"type","value":":","line":2,"start":22,"end":23},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":2,"start":24,"end":29},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":29,"end":30},{"type":"T_LCURLY","context":"type","value":"{","line":2,"start":30,"end":31},{"type":"T_IDENTIFIER","context":"normal","value":"id","line":3,"start":36,"end":38},{"type":"T_COLON","context":"type","value":":","line":3,"start":38,"end":39},{"type":"T_STRING_TYPE","context":"type","value":"string","line":3,"start":40,"end":46},{"type":"T_COMMA","context":"type","value":",","line":3,"start":46,"end":47},{"type":"T_IDENTIFIER","context":"normal","value":"name","line":4,"start":52,"end":56},{"type":"T_COLON","context":"type","value":":","line":4,"start":56,"end":57},{"type":"T_STRING_TYPE","context":"type","value":"string","line":4,"start":58,"end":64},{"type":"T_COMMA","context":"type","value":",","line":4,"start":64,"end":65},{"type":"T_IDENTIFIER","context":"normal","value":"age","line":5,"start":70,"end":73},{"type":"T_COLON","context":"type","value":":","line":5,"start":73,"end":74},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":5,"start":75,"end":81},{"type":"T_COMMA","context":"type","value":",","line":5,"start":81,"end":82},{"type":"T_IDENTIFIER","context":"normal","value":"phoneNumber","line":6,"start":87,"end":98},{"type":"T_COLON","context":"type","value":":","line":6,"start":98,"end":99},{"type":"T_STRING_TYPE","context":"type","value":"string","line":6,"start":100,"end":106},{"type":"T_COMMA","context":"type","value":",","line":6,"start":106,"end":107},{"type":"T_RCURLY","context":"type","value":"}","line":7,"start":110,"end":111},{"type":"T_GREATER_THAN","context":"type","value":">","line":7,"start":111,"end":112},{"type":"T_COMMA","context":"type","value":",","line":7,"start":112,"end":113},{"type":"T_IDENTIFIER","context":"normal","value":"activeUserID","line":8,"start":116,"end":128},{"type":"T_COLON","context":"type","value":":","line":8,"start":128,"end":129},{"type":"T_STRING_TYPE","context":"type","value":"string","line":8,"start":130,"end":136},{"type":"T_COMMA","context":"type","value":",","line":8,"start":136,"end":137},{"type":"Line","context":"comment","value":"// ...","line":9,"start":140,"end":146},{"type":"T_RCURLY","context":"type","value":"}","line":10,"start":147,"end":148},{"type":"T_SEMICOLON","context":"normal","value":";","line":10,"start":148,"end":149}],"errors":[]}
We can use this type alias to make sure reducers work correctly.
Typing Redux state immutability
Redux state is meant to be immutable:
creating a new state object instead of changing properties on a single object.
You can enforce this in Flow by making every property effectively “read-only”
using “covariant” properties throughout your state object.
1
2
3
4
5
6
7
8
9
10
|
type State = {
+users: Array<{
+id: string,
+name: string,
+age: number,
+phoneNumber: string,
}>,
+activeUserID: string,
};
|
{"value":"type State = {\n +users: Array<{\n +id: string,\n +name: string,\n +age: number,\n +phoneNumber: string,\n }>,\n +activeUserID: string,\n // ...\n};\n","tokens":[{"type":"T_TYPE","context":"normal","value":"type","line":1,"start":0,"end":4},{"type":"T_IDENTIFIER","context":"type","value":"State","line":1,"start":5,"end":10},{"type":"T_ASSIGN","context":"type","value":"=","line":1,"start":11,"end":12},{"type":"T_LCURLY","context":"type","value":"{","line":1,"start":13,"end":14},{"type":"T_PLUS","context":"type","value":"+","line":2,"start":17,"end":18},{"type":"T_IDENTIFIER","context":"normal","value":"users","line":2,"start":18,"end":23},{"type":"T_COLON","context":"type","value":":","line":2,"start":23,"end":24},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":2,"start":25,"end":30},{"type":"T_LESS_THAN","context":"type","value":"<","line":2,"start":30,"end":31},{"type":"T_LCURLY","context":"type","value":"{","line":2,"start":31,"end":32},{"type":"T_PLUS","context":"type","value":"+","line":3,"start":37,"end":38},{"type":"T_IDENTIFIER","context":"normal","value":"id","line":3,"start":38,"end":40},{"type":"T_COLON","context":"type","value":":","line":3,"start":40,"end":41},{"type":"T_STRING_TYPE","context":"type","value":"string","line":3,"start":42,"end":48},{"type":"T_COMMA","context":"type","value":",","line":3,"start":48,"end":49},{"type":"T_PLUS","context":"type","value":"+","line":4,"start":54,"end":55},{"type":"T_IDENTIFIER","context":"normal","value":"name","line":4,"start":55,"end":59},{"type":"T_COLON","context":"type","value":":","line":4,"start":59,"end":60},{"type":"T_STRING_TYPE","context":"type","value":"string","line":4,"start":61,"end":67},{"type":"T_COMMA","context":"type","value":",","line":4,"start":67,"end":68},{"type":"T_PLUS","context":"type","value":"+","line":5,"start":73,"end":74},{"type":"T_IDENTIFIER","context":"normal","value":"age","line":5,"start":74,"end":77},{"type":"T_COLON","context":"type","value":":","line":5,"start":77,"end":78},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":5,"start":79,"end":85},{"type":"T_COMMA","context":"type","value":",","line":5,"start":85,"end":86},{"type":"T_PLUS","context":"type","value":"+","line":6,"start":91,"end":92},{"type":"T_IDENTIFIER","context":"normal","value":"phoneNumber","line":6,"start":92,"end":103},{"type":"T_COLON","context":"type","value":":","line":6,"start":103,"end":104},{"type":"T_STRING_TYPE","context":"type","value":"string","line":6,"start":105,"end":111},{"type":"T_COMMA","context":"type","value":",","line":6,"start":111,"end":112},{"type":"T_RCURLY","context":"type","value":"}","line":7,"start":115,"end":116},{"type":"T_GREATER_THAN","context":"type","value":">","line":7,"start":116,"end":117},{"type":"T_COMMA","context":"type","value":",","line":7,"start":117,"end":118},{"type":"T_PLUS","context":"type","value":"+","line":8,"start":121,"end":122},{"type":"T_IDENTIFIER","context":"normal","value":"activeUserID","line":8,"start":122,"end":134},{"type":"T_COLON","context":"type","value":":","line":8,"start":134,"end":135},{"type":"T_STRING_TYPE","context":"type","value":"string","line":8,"start":136,"end":142},{"type":"T_COMMA","context":"type","value":",","line":8,"start":142,"end":143},{"type":"Line","context":"comment","value":"// ...","line":9,"start":146,"end":152},{"type":"T_RCURLY","context":"type","value":"}","line":10,"start":153,"end":154},{"type":"T_SEMICOLON","context":"normal","value":";","line":10,"start":154,"end":155}],"errors":[]}
Now Flow will complain when you try to write to any of these properties.
1
2
3
4
5
6
7
8
9
10
|
type State = {
+foo: string
};
let state: State = {
foo: "foo"
};
state.foo = "bar";
|
Cannot assign `"bar"` to `state.foo` because property `foo` is not writable. [cannot-write]
{"value":"// @flow\ntype State = {\n +foo: string\n};\n\nlet state: State = {\n foo: \"foo\"\n};\n\nstate.foo = \"bar\"; // Error!\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_TYPE","context":"normal","value":"type","line":2,"start":9,"end":13},{"type":"T_IDENTIFIER","context":"type","value":"State","line":2,"start":14,"end":19},{"type":"T_ASSIGN","context":"type","value":"=","line":2,"start":20,"end":21},{"type":"T_LCURLY","context":"type","value":"{","line":2,"start":22,"end":23},{"type":"T_PLUS","context":"type","value":"+","line":3,"start":26,"end":27},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":3,"start":27,"end":30},{"type":"T_COLON","context":"type","value":":","line":3,"start":30,"end":31},{"type":"T_STRING_TYPE","context":"type","value":"string","line":3,"start":32,"end":38},{"type":"T_RCURLY","context":"type","value":"}","line":4,"start":39,"end":40},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":40,"end":41},{"type":"T_LET","context":"normal","value":"let","line":6,"start":43,"end":46},{"type":"T_IDENTIFIER","context":"normal","value":"state","line":6,"start":47,"end":52},{"type":"T_COLON","context":"type","value":":","line":6,"start":52,"end":53},{"type":"T_IDENTIFIER","context":"type","value":"State","line":6,"start":54,"end":59},{"type":"T_ASSIGN","context":"normal","value":"=","line":6,"start":60,"end":61},{"type":"T_LCURLY","context":"normal","value":"{","line":6,"start":62,"end":63},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":7,"start":66,"end":69},{"type":"T_COLON","context":"normal","value":":","line":7,"start":69,"end":70},{"type":"T_STRING","context":"normal","value":"\"foo\"","line":7,"start":71,"end":76},{"type":"T_RCURLY","context":"normal","value":"}","line":8,"start":77,"end":78},{"type":"T_SEMICOLON","context":"normal","value":";","line":8,"start":78,"end":79},{"type":"T_IDENTIFIER","context":"normal","value":"state","line":10,"start":81,"end":86},{"type":"T_PERIOD","context":"normal","value":".","line":10,"start":86,"end":87},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":10,"start":87,"end":90},{"type":"T_ASSIGN","context":"normal","value":"=","line":10,"start":91,"end":92},{"type":"T_STRING","context":"normal","value":"\"bar\"","line":10,"start":93,"end":98},{"type":"T_SEMICOLON","context":"normal","value":";","line":10,"start":98,"end":99},{"type":"Line","context":"comment","value":"// Error!","line":10,"start":100,"end":109}],"errors":[{"id":"E1","messages":[{"id":"E1M1","description":"Cannot assign `\"bar\"` to `state.foo` because property `foo` is not writable. [cannot-write]","context":"state.foo = \"bar\"; // Error!","source":"-","start":{"line":10,"column":7,"offset":87},"end":{"line":10,"column":9,"offset":90}}],"operation":null}]}
Typing Redux actions
The base type for Redux actions
is an object with a type
property.
1
2
3
|
type Action = {
+type: string,
};
|
{"value":"type Action = {\n +type: string,\n};\n","tokens":[{"type":"T_TYPE","context":"normal","value":"type","line":1,"start":0,"end":4},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":1,"start":5,"end":11},{"type":"T_ASSIGN","context":"type","value":"=","line":1,"start":12,"end":13},{"type":"T_LCURLY","context":"type","value":"{","line":1,"start":14,"end":15},{"type":"T_PLUS","context":"type","value":"+","line":2,"start":18,"end":19},{"type":"T_TYPE","context":"normal","value":"type","line":2,"start":19,"end":23},{"type":"T_COLON","context":"type","value":":","line":2,"start":23,"end":24},{"type":"T_STRING_TYPE","context":"type","value":"string","line":2,"start":25,"end":31},{"type":"T_COMMA","context":"type","value":",","line":2,"start":31,"end":32},{"type":"T_RCURLY","context":"type","value":"}","line":3,"start":33,"end":34},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":34,"end":35}],"errors":[]}
But you’ll want to use more specific types for your actions using disjoint
unions and each individual type of action.
1
2
3
4
|
type Action =
| { type: "FOO", foo: number }
| { type: "BAR", bar: boolean }
| { type: "BAZ", baz: string };
|
{"value":"type Action =\n | { type: \"FOO\", foo: number }\n | { type: \"BAR\", bar: boolean }\n | { type: \"BAZ\", baz: string };\n","tokens":[{"type":"T_TYPE","context":"normal","value":"type","line":1,"start":0,"end":4},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":1,"start":5,"end":11},{"type":"T_ASSIGN","context":"type","value":"=","line":1,"start":12,"end":13},{"type":"T_BIT_OR","context":"type","value":"|","line":2,"start":16,"end":17},{"type":"T_LCURLY","context":"type","value":"{","line":2,"start":18,"end":19},{"type":"T_TYPE","context":"normal","value":"type","line":2,"start":20,"end":24},{"type":"T_COLON","context":"type","value":":","line":2,"start":24,"end":25},{"type":"T_STRING","context":"type","value":"\"FOO\"","line":2,"start":26,"end":31},{"type":"T_COMMA","context":"type","value":",","line":2,"start":31,"end":32},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":2,"start":33,"end":36},{"type":"T_COLON","context":"type","value":":","line":2,"start":36,"end":37},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":38,"end":44},{"type":"T_RCURLY","context":"type","value":"}","line":2,"start":45,"end":46},{"type":"T_BIT_OR","context":"type","value":"|","line":3,"start":49,"end":50},{"type":"T_LCURLY","context":"type","value":"{","line":3,"start":51,"end":52},{"type":"T_TYPE","context":"normal","value":"type","line":3,"start":53,"end":57},{"type":"T_COLON","context":"type","value":":","line":3,"start":57,"end":58},{"type":"T_STRING","context":"type","value":"\"BAR\"","line":3,"start":59,"end":64},{"type":"T_COMMA","context":"type","value":",","line":3,"start":64,"end":65},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":3,"start":66,"end":69},{"type":"T_COLON","context":"type","value":":","line":3,"start":69,"end":70},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":3,"start":71,"end":78},{"type":"T_RCURLY","context":"type","value":"}","line":3,"start":79,"end":80},{"type":"T_BIT_OR","context":"type","value":"|","line":4,"start":83,"end":84},{"type":"T_LCURLY","context":"type","value":"{","line":4,"start":85,"end":86},{"type":"T_TYPE","context":"normal","value":"type","line":4,"start":87,"end":91},{"type":"T_COLON","context":"type","value":":","line":4,"start":91,"end":92},{"type":"T_STRING","context":"type","value":"\"BAZ\"","line":4,"start":93,"end":98},{"type":"T_COMMA","context":"type","value":",","line":4,"start":98,"end":99},{"type":"T_IDENTIFIER","context":"normal","value":"baz","line":4,"start":100,"end":103},{"type":"T_COLON","context":"type","value":":","line":4,"start":103,"end":104},{"type":"T_STRING_TYPE","context":"type","value":"string","line":4,"start":105,"end":111},{"type":"T_RCURLY","context":"type","value":"}","line":4,"start":112,"end":113},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":113,"end":114}],"errors":[]}
Using disjoint unions, Flow will be able to understand your reducers much
better.
Typing Redux action creators
In order to type your Redux action creators,
you’ll want to split up your Action
disjoint union into separate action
types.
1
2
3
4
5
6
|
type FooAction = { type: "FOO", foo: number };
type BarAction = { type: "BAR", bar: boolean };
type Action =
| FooAction
| BarAction;
|
{"value":"type FooAction = { type: \"FOO\", foo: number };\ntype BarAction = { type: \"BAR\", bar: boolean };\n\ntype Action =\n | FooAction\n | BarAction;\n","tokens":[{"type":"T_TYPE","context":"normal","value":"type","line":1,"start":0,"end":4},{"type":"T_IDENTIFIER","context":"type","value":"FooAction","line":1,"start":5,"end":14},{"type":"T_ASSIGN","context":"type","value":"=","line":1,"start":15,"end":16},{"type":"T_LCURLY","context":"type","value":"{","line":1,"start":17,"end":18},{"type":"T_TYPE","context":"normal","value":"type","line":1,"start":19,"end":23},{"type":"T_COLON","context":"type","value":":","line":1,"start":23,"end":24},{"type":"T_STRING","context":"type","value":"\"FOO\"","line":1,"start":25,"end":30},{"type":"T_COMMA","context":"type","value":",","line":1,"start":30,"end":31},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":1,"start":32,"end":35},{"type":"T_COLON","context":"type","value":":","line":1,"start":35,"end":36},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":1,"start":37,"end":43},{"type":"T_RCURLY","context":"type","value":"}","line":1,"start":44,"end":45},{"type":"T_SEMICOLON","context":"normal","value":";","line":1,"start":45,"end":46},{"type":"T_TYPE","context":"normal","value":"type","line":2,"start":47,"end":51},{"type":"T_IDENTIFIER","context":"type","value":"BarAction","line":2,"start":52,"end":61},{"type":"T_ASSIGN","context":"type","value":"=","line":2,"start":62,"end":63},{"type":"T_LCURLY","context":"type","value":"{","line":2,"start":64,"end":65},{"type":"T_TYPE","context":"normal","value":"type","line":2,"start":66,"end":70},{"type":"T_COLON","context":"type","value":":","line":2,"start":70,"end":71},{"type":"T_STRING","context":"type","value":"\"BAR\"","line":2,"start":72,"end":77},{"type":"T_COMMA","context":"type","value":",","line":2,"start":77,"end":78},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":2,"start":79,"end":82},{"type":"T_COLON","context":"type","value":":","line":2,"start":82,"end":83},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":2,"start":84,"end":91},{"type":"T_RCURLY","context":"type","value":"}","line":2,"start":92,"end":93},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":93,"end":94},{"type":"T_TYPE","context":"normal","value":"type","line":4,"start":96,"end":100},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":4,"start":101,"end":107},{"type":"T_ASSIGN","context":"type","value":"=","line":4,"start":108,"end":109},{"type":"T_BIT_OR","context":"type","value":"|","line":5,"start":112,"end":113},{"type":"T_IDENTIFIER","context":"type","value":"FooAction","line":5,"start":114,"end":123},{"type":"T_BIT_OR","context":"type","value":"|","line":6,"start":126,"end":127},{"type":"T_IDENTIFIER","context":"type","value":"BarAction","line":6,"start":128,"end":137},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":137,"end":138}],"errors":[]}
Then to type the action creator, just add a return type of the appropriate
action.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
type FooAction = { type: "FOO", foo: number };
type BarAction = { type: "BAR", bar: boolean };
type Action =
| FooAction
| BarAction;
function foo(value: number): FooAction {
return { type: "FOO", foo: value };
}
function bar(value: boolean): BarAction {
return { type: "BAR", bar: value };
}
|
{"value":"// @flow\ntype FooAction = { type: \"FOO\", foo: number };\ntype BarAction = { type: \"BAR\", bar: boolean };\n\ntype Action =\n | FooAction\n | BarAction;\n\nfunction foo(value: number): FooAction {\n return { type: \"FOO\", foo: value };\n}\n\nfunction bar(value: boolean): BarAction {\n return { type: \"BAR\", bar: value };\n}\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_TYPE","context":"normal","value":"type","line":2,"start":9,"end":13},{"type":"T_IDENTIFIER","context":"type","value":"FooAction","line":2,"start":14,"end":23},{"type":"T_ASSIGN","context":"type","value":"=","line":2,"start":24,"end":25},{"type":"T_LCURLY","context":"type","value":"{","line":2,"start":26,"end":27},{"type":"T_TYPE","context":"normal","value":"type","line":2,"start":28,"end":32},{"type":"T_COLON","context":"type","value":":","line":2,"start":32,"end":33},{"type":"T_STRING","context":"type","value":"\"FOO\"","line":2,"start":34,"end":39},{"type":"T_COMMA","context":"type","value":",","line":2,"start":39,"end":40},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":2,"start":41,"end":44},{"type":"T_COLON","context":"type","value":":","line":2,"start":44,"end":45},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":46,"end":52},{"type":"T_RCURLY","context":"type","value":"}","line":2,"start":53,"end":54},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":54,"end":55},{"type":"T_TYPE","context":"normal","value":"type","line":3,"start":56,"end":60},{"type":"T_IDENTIFIER","context":"type","value":"BarAction","line":3,"start":61,"end":70},{"type":"T_ASSIGN","context":"type","value":"=","line":3,"start":71,"end":72},{"type":"T_LCURLY","context":"type","value":"{","line":3,"start":73,"end":74},{"type":"T_TYPE","context":"normal","value":"type","line":3,"start":75,"end":79},{"type":"T_COLON","context":"type","value":":","line":3,"start":79,"end":80},{"type":"T_STRING","context":"type","value":"\"BAR\"","line":3,"start":81,"end":86},{"type":"T_COMMA","context":"type","value":",","line":3,"start":86,"end":87},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":3,"start":88,"end":91},{"type":"T_COLON","context":"type","value":":","line":3,"start":91,"end":92},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":3,"start":93,"end":100},{"type":"T_RCURLY","context":"type","value":"}","line":3,"start":101,"end":102},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":102,"end":103},{"type":"T_TYPE","context":"normal","value":"type","line":5,"start":105,"end":109},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":5,"start":110,"end":116},{"type":"T_ASSIGN","context":"type","value":"=","line":5,"start":117,"end":118},{"type":"T_BIT_OR","context":"type","value":"|","line":6,"start":121,"end":122},{"type":"T_IDENTIFIER","context":"type","value":"FooAction","line":6,"start":123,"end":132},{"type":"T_BIT_OR","context":"type","value":"|","line":7,"start":135,"end":136},{"type":"T_IDENTIFIER","context":"type","value":"BarAction","line":7,"start":137,"end":146},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":146,"end":147},{"type":"T_FUNCTION","context":"normal","value":"function","line":9,"start":149,"end":157},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":9,"start":158,"end":161},{"type":"T_LPAREN","context":"normal","value":"(","line":9,"start":161,"end":162},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":9,"start":162,"end":167},{"type":"T_COLON","context":"type","value":":","line":9,"start":167,"end":168},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":9,"start":169,"end":175},{"type":"T_RPAREN","context":"normal","value":")","line":9,"start":175,"end":176},{"type":"T_COLON","context":"type","value":":","line":9,"start":176,"end":177},{"type":"T_IDENTIFIER","context":"type","value":"FooAction","line":9,"start":178,"end":187},{"type":"T_LCURLY","context":"normal","value":"{","line":9,"start":188,"end":189},{"type":"T_RETURN","context":"normal","value":"return","line":10,"start":192,"end":198},{"type":"T_LCURLY","context":"normal","value":"{","line":10,"start":199,"end":200},{"type":"T_TYPE","context":"normal","value":"type","line":10,"start":201,"end":205},{"type":"T_COLON","context":"normal","value":":","line":10,"start":205,"end":206},{"type":"T_STRING","context":"normal","value":"\"FOO\"","line":10,"start":207,"end":212},{"type":"T_COMMA","context":"normal","value":",","line":10,"start":212,"end":213},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":10,"start":214,"end":217},{"type":"T_COLON","context":"normal","value":":","line":10,"start":217,"end":218},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":10,"start":219,"end":224},{"type":"T_RCURLY","context":"normal","value":"}","line":10,"start":225,"end":226},{"type":"T_SEMICOLON","context":"normal","value":";","line":10,"start":226,"end":227},{"type":"T_RCURLY","context":"normal","value":"}","line":11,"start":228,"end":229},{"type":"T_FUNCTION","context":"normal","value":"function","line":13,"start":231,"end":239},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":13,"start":240,"end":243},{"type":"T_LPAREN","context":"normal","value":"(","line":13,"start":243,"end":244},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":13,"start":244,"end":249},{"type":"T_COLON","context":"type","value":":","line":13,"start":249,"end":250},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":13,"start":251,"end":258},{"type":"T_RPAREN","context":"normal","value":")","line":13,"start":258,"end":259},{"type":"T_COLON","context":"type","value":":","line":13,"start":259,"end":260},{"type":"T_IDENTIFIER","context":"type","value":"BarAction","line":13,"start":261,"end":270},{"type":"T_LCURLY","context":"normal","value":"{","line":13,"start":271,"end":272},{"type":"T_RETURN","context":"normal","value":"return","line":14,"start":275,"end":281},{"type":"T_LCURLY","context":"normal","value":"{","line":14,"start":282,"end":283},{"type":"T_TYPE","context":"normal","value":"type","line":14,"start":284,"end":288},{"type":"T_COLON","context":"normal","value":":","line":14,"start":288,"end":289},{"type":"T_STRING","context":"normal","value":"\"BAR\"","line":14,"start":290,"end":295},{"type":"T_COMMA","context":"normal","value":",","line":14,"start":295,"end":296},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":14,"start":297,"end":300},{"type":"T_COLON","context":"normal","value":":","line":14,"start":300,"end":301},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":14,"start":302,"end":307},{"type":"T_RCURLY","context":"normal","value":"}","line":14,"start":308,"end":309},{"type":"T_SEMICOLON","context":"normal","value":";","line":14,"start":309,"end":310},{"type":"T_RCURLY","context":"normal","value":"}","line":15,"start":311,"end":312}],"errors":[]}
Typing Redux thunk actions
In order to type your Redux thunk actions,
you’ll add types for ThunkAction
as a function Dispatch
, and GetState
. GetState
is a function that returns an Object
. Dispatch
accepts a disjoint union of Action
, ThunkAction
, PromiseAction
and Array<Action>
and can return any
.
1
2
3
4
|
type Dispatch = (action: Action | ThunkAction | PromiseAction) => any;
type GetState = () => State;
type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
type PromiseAction = Promise<Action>;
|
{"value":"type Dispatch = (action: Action | ThunkAction | PromiseAction) => any;\ntype GetState = () => State;\ntype ThunkAction = (dispatch: Dispatch, getState: GetState) => any;\ntype PromiseAction = Promise<Action>;\n","tokens":[{"type":"T_TYPE","context":"normal","value":"type","line":1,"start":0,"end":4},{"type":"T_IDENTIFIER","context":"type","value":"Dispatch","line":1,"start":5,"end":13},{"type":"T_ASSIGN","context":"type","value":"=","line":1,"start":14,"end":15},{"type":"T_LPAREN","context":"type","value":"(","line":1,"start":16,"end":17},{"type":"T_IDENTIFIER","context":"normal","value":"action","line":1,"start":17,"end":23},{"type":"T_COLON","context":"type","value":":","line":1,"start":23,"end":24},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":1,"start":25,"end":31},{"type":"T_BIT_OR","context":"type","value":"|","line":1,"start":32,"end":33},{"type":"T_IDENTIFIER","context":"type","value":"ThunkAction","line":1,"start":34,"end":45},{"type":"T_BIT_OR","context":"type","value":"|","line":1,"start":46,"end":47},{"type":"T_IDENTIFIER","context":"type","value":"PromiseAction","line":1,"start":48,"end":61},{"type":"T_RPAREN","context":"type","value":")","line":1,"start":61,"end":62},{"type":"T_ARROW","context":"type","value":"=>","line":1,"start":63,"end":65},{"type":"T_ANY_TYPE","context":"type","value":"any","line":1,"start":66,"end":69},{"type":"T_SEMICOLON","context":"normal","value":";","line":1,"start":69,"end":70},{"type":"T_TYPE","context":"normal","value":"type","line":2,"start":71,"end":75},{"type":"T_IDENTIFIER","context":"type","value":"GetState","line":2,"start":76,"end":84},{"type":"T_ASSIGN","context":"type","value":"=","line":2,"start":85,"end":86},{"type":"T_LPAREN","context":"type","value":"(","line":2,"start":87,"end":88},{"type":"T_RPAREN","context":"type","value":")","line":2,"start":88,"end":89},{"type":"T_ARROW","context":"type","value":"=>","line":2,"start":90,"end":92},{"type":"T_IDENTIFIER","context":"type","value":"State","line":2,"start":93,"end":98},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":98,"end":99},{"type":"T_TYPE","context":"normal","value":"type","line":3,"start":100,"end":104},{"type":"T_IDENTIFIER","context":"type","value":"ThunkAction","line":3,"start":105,"end":116},{"type":"T_ASSIGN","context":"type","value":"=","line":3,"start":117,"end":118},{"type":"T_LPAREN","context":"type","value":"(","line":3,"start":119,"end":120},{"type":"T_IDENTIFIER","context":"normal","value":"dispatch","line":3,"start":120,"end":128},{"type":"T_COLON","context":"type","value":":","line":3,"start":128,"end":129},{"type":"T_IDENTIFIER","context":"type","value":"Dispatch","line":3,"start":130,"end":138},{"type":"T_COMMA","context":"type","value":",","line":3,"start":138,"end":139},{"type":"T_IDENTIFIER","context":"normal","value":"getState","line":3,"start":140,"end":148},{"type":"T_COLON","context":"type","value":":","line":3,"start":148,"end":149},{"type":"T_IDENTIFIER","context":"type","value":"GetState","line":3,"start":150,"end":158},{"type":"T_RPAREN","context":"type","value":")","line":3,"start":158,"end":159},{"type":"T_ARROW","context":"type","value":"=>","line":3,"start":160,"end":162},{"type":"T_ANY_TYPE","context":"type","value":"any","line":3,"start":163,"end":166},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":166,"end":167},{"type":"T_TYPE","context":"normal","value":"type","line":4,"start":168,"end":172},{"type":"T_IDENTIFIER","context":"type","value":"PromiseAction","line":4,"start":173,"end":186},{"type":"T_ASSIGN","context":"type","value":"=","line":4,"start":187,"end":188},{"type":"T_IDENTIFIER","context":"type","value":"Promise","line":4,"start":189,"end":196},{"type":"T_LESS_THAN","context":"type","value":"<","line":4,"start":196,"end":197},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":4,"start":197,"end":203},{"type":"T_GREATER_THAN","context":"type","value":">","line":4,"start":203,"end":204},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":204,"end":205}],"errors":[]}
Then to type a thunk action creator, add a return type of a ThunkAction
to your action creator.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
type Action =
| { type: "FOO", foo: number }
| { type: "BAR", bar: boolean };
type GetState = () => State;
type PromiseAction = Promise<Action>;
type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
type Dispatch = (action: Action | ThunkAction | PromiseAction | Array<Action>) => any;
function foo(): ThunkAction {
return (dispatch, getState) => {
const baz = getState().baz
dispatch({ type: "BAR", bar: true })
doSomethingAsync(baz)
.then(value => {
dispatch({ type: "FOO", foo: value })
})
}
}
|
{"value":"type Action =\n | { type: \"FOO\", foo: number }\n | { type: \"BAR\", bar: boolean };\n\ntype GetState = () => State;\ntype PromiseAction = Promise<Action>;\ntype ThunkAction = (dispatch: Dispatch, getState: GetState) => any;\ntype Dispatch = (action: Action | ThunkAction | PromiseAction | Array<Action>) => any;\n\n\nfunction foo(): ThunkAction {\n return (dispatch, getState) => {\n const baz = getState().baz\n dispatch({ type: \"BAR\", bar: true })\n doSomethingAsync(baz)\n .then(value => {\n dispatch({ type: \"FOO\", foo: value })\n })\n }\n}\n","tokens":[{"type":"T_TYPE","context":"normal","value":"type","line":1,"start":0,"end":4},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":1,"start":5,"end":11},{"type":"T_ASSIGN","context":"type","value":"=","line":1,"start":12,"end":13},{"type":"T_BIT_OR","context":"type","value":"|","line":2,"start":16,"end":17},{"type":"T_LCURLY","context":"type","value":"{","line":2,"start":18,"end":19},{"type":"T_TYPE","context":"normal","value":"type","line":2,"start":20,"end":24},{"type":"T_COLON","context":"type","value":":","line":2,"start":24,"end":25},{"type":"T_STRING","context":"type","value":"\"FOO\"","line":2,"start":26,"end":31},{"type":"T_COMMA","context":"type","value":",","line":2,"start":31,"end":32},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":2,"start":33,"end":36},{"type":"T_COLON","context":"type","value":":","line":2,"start":36,"end":37},{"type":"T_NUMBER_TYPE","context":"type","value":"number","line":2,"start":38,"end":44},{"type":"T_RCURLY","context":"type","value":"}","line":2,"start":45,"end":46},{"type":"T_BIT_OR","context":"type","value":"|","line":3,"start":49,"end":50},{"type":"T_LCURLY","context":"type","value":"{","line":3,"start":51,"end":52},{"type":"T_TYPE","context":"normal","value":"type","line":3,"start":53,"end":57},{"type":"T_COLON","context":"type","value":":","line":3,"start":57,"end":58},{"type":"T_STRING","context":"type","value":"\"BAR\"","line":3,"start":59,"end":64},{"type":"T_COMMA","context":"type","value":",","line":3,"start":64,"end":65},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":3,"start":66,"end":69},{"type":"T_COLON","context":"type","value":":","line":3,"start":69,"end":70},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":3,"start":71,"end":78},{"type":"T_RCURLY","context":"type","value":"}","line":3,"start":79,"end":80},{"type":"T_SEMICOLON","context":"normal","value":";","line":3,"start":80,"end":81},{"type":"T_TYPE","context":"normal","value":"type","line":5,"start":83,"end":87},{"type":"T_IDENTIFIER","context":"type","value":"GetState","line":5,"start":88,"end":96},{"type":"T_ASSIGN","context":"type","value":"=","line":5,"start":97,"end":98},{"type":"T_LPAREN","context":"type","value":"(","line":5,"start":99,"end":100},{"type":"T_RPAREN","context":"type","value":")","line":5,"start":100,"end":101},{"type":"T_ARROW","context":"type","value":"=>","line":5,"start":102,"end":104},{"type":"T_IDENTIFIER","context":"type","value":"State","line":5,"start":105,"end":110},{"type":"T_SEMICOLON","context":"normal","value":";","line":5,"start":110,"end":111},{"type":"T_TYPE","context":"normal","value":"type","line":6,"start":112,"end":116},{"type":"T_IDENTIFIER","context":"type","value":"PromiseAction","line":6,"start":117,"end":130},{"type":"T_ASSIGN","context":"type","value":"=","line":6,"start":131,"end":132},{"type":"T_IDENTIFIER","context":"type","value":"Promise","line":6,"start":133,"end":140},{"type":"T_LESS_THAN","context":"type","value":"<","line":6,"start":140,"end":141},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":6,"start":141,"end":147},{"type":"T_GREATER_THAN","context":"type","value":">","line":6,"start":147,"end":148},{"type":"T_SEMICOLON","context":"normal","value":";","line":6,"start":148,"end":149},{"type":"T_TYPE","context":"normal","value":"type","line":7,"start":150,"end":154},{"type":"T_IDENTIFIER","context":"type","value":"ThunkAction","line":7,"start":155,"end":166},{"type":"T_ASSIGN","context":"type","value":"=","line":7,"start":167,"end":168},{"type":"T_LPAREN","context":"type","value":"(","line":7,"start":169,"end":170},{"type":"T_IDENTIFIER","context":"normal","value":"dispatch","line":7,"start":170,"end":178},{"type":"T_COLON","context":"type","value":":","line":7,"start":178,"end":179},{"type":"T_IDENTIFIER","context":"type","value":"Dispatch","line":7,"start":180,"end":188},{"type":"T_COMMA","context":"type","value":",","line":7,"start":188,"end":189},{"type":"T_IDENTIFIER","context":"normal","value":"getState","line":7,"start":190,"end":198},{"type":"T_COLON","context":"type","value":":","line":7,"start":198,"end":199},{"type":"T_IDENTIFIER","context":"type","value":"GetState","line":7,"start":200,"end":208},{"type":"T_RPAREN","context":"type","value":")","line":7,"start":208,"end":209},{"type":"T_ARROW","context":"type","value":"=>","line":7,"start":210,"end":212},{"type":"T_ANY_TYPE","context":"type","value":"any","line":7,"start":213,"end":216},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":216,"end":217},{"type":"T_TYPE","context":"normal","value":"type","line":8,"start":218,"end":222},{"type":"T_IDENTIFIER","context":"type","value":"Dispatch","line":8,"start":223,"end":231},{"type":"T_ASSIGN","context":"type","value":"=","line":8,"start":232,"end":233},{"type":"T_LPAREN","context":"type","value":"(","line":8,"start":234,"end":235},{"type":"T_IDENTIFIER","context":"normal","value":"action","line":8,"start":235,"end":241},{"type":"T_COLON","context":"type","value":":","line":8,"start":241,"end":242},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":8,"start":243,"end":249},{"type":"T_BIT_OR","context":"type","value":"|","line":8,"start":250,"end":251},{"type":"T_IDENTIFIER","context":"type","value":"ThunkAction","line":8,"start":252,"end":263},{"type":"T_BIT_OR","context":"type","value":"|","line":8,"start":264,"end":265},{"type":"T_IDENTIFIER","context":"type","value":"PromiseAction","line":8,"start":266,"end":279},{"type":"T_BIT_OR","context":"type","value":"|","line":8,"start":280,"end":281},{"type":"T_IDENTIFIER","context":"type","value":"Array","line":8,"start":282,"end":287},{"type":"T_LESS_THAN","context":"type","value":"<","line":8,"start":287,"end":288},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":8,"start":288,"end":294},{"type":"T_GREATER_THAN","context":"type","value":">","line":8,"start":294,"end":295},{"type":"T_RPAREN","context":"type","value":")","line":8,"start":295,"end":296},{"type":"T_ARROW","context":"type","value":"=>","line":8,"start":297,"end":299},{"type":"T_ANY_TYPE","context":"type","value":"any","line":8,"start":300,"end":303},{"type":"T_SEMICOLON","context":"normal","value":";","line":8,"start":303,"end":304},{"type":"T_FUNCTION","context":"normal","value":"function","line":11,"start":307,"end":315},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":11,"start":316,"end":319},{"type":"T_LPAREN","context":"normal","value":"(","line":11,"start":319,"end":320},{"type":"T_RPAREN","context":"normal","value":")","line":11,"start":320,"end":321},{"type":"T_COLON","context":"type","value":":","line":11,"start":321,"end":322},{"type":"T_IDENTIFIER","context":"type","value":"ThunkAction","line":11,"start":323,"end":334},{"type":"T_LCURLY","context":"normal","value":"{","line":11,"start":335,"end":336},{"type":"T_RETURN","context":"normal","value":"return","line":12,"start":339,"end":345},{"type":"T_LPAREN","context":"normal","value":"(","line":12,"start":346,"end":347},{"type":"T_IDENTIFIER","context":"normal","value":"dispatch","line":12,"start":347,"end":355},{"type":"T_COMMA","context":"normal","value":",","line":12,"start":355,"end":356},{"type":"T_IDENTIFIER","context":"normal","value":"getState","line":12,"start":357,"end":365},{"type":"T_RPAREN","context":"normal","value":")","line":12,"start":365,"end":366},{"type":"T_ARROW","context":"normal","value":"=>","line":12,"start":367,"end":369},{"type":"T_LCURLY","context":"normal","value":"{","line":12,"start":370,"end":371},{"type":"T_CONST","context":"normal","value":"const","line":13,"start":376,"end":381},{"type":"T_IDENTIFIER","context":"normal","value":"baz","line":13,"start":382,"end":385},{"type":"T_ASSIGN","context":"normal","value":"=","line":13,"start":386,"end":387},{"type":"T_IDENTIFIER","context":"normal","value":"getState","line":13,"start":388,"end":396},{"type":"T_LPAREN","context":"normal","value":"(","line":13,"start":396,"end":397},{"type":"T_RPAREN","context":"normal","value":")","line":13,"start":397,"end":398},{"type":"T_PERIOD","context":"normal","value":".","line":13,"start":398,"end":399},{"type":"T_IDENTIFIER","context":"normal","value":"baz","line":13,"start":399,"end":402},{"type":"T_IDENTIFIER","context":"normal","value":"dispatch","line":14,"start":407,"end":415},{"type":"T_LPAREN","context":"normal","value":"(","line":14,"start":415,"end":416},{"type":"T_LCURLY","context":"normal","value":"{","line":14,"start":416,"end":417},{"type":"T_TYPE","context":"normal","value":"type","line":14,"start":418,"end":422},{"type":"T_COLON","context":"normal","value":":","line":14,"start":422,"end":423},{"type":"T_STRING","context":"normal","value":"\"BAR\"","line":14,"start":424,"end":429},{"type":"T_COMMA","context":"normal","value":",","line":14,"start":429,"end":430},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":14,"start":431,"end":434},{"type":"T_COLON","context":"normal","value":":","line":14,"start":434,"end":435},{"type":"T_TRUE","context":"normal","value":"true","line":14,"start":436,"end":440},{"type":"T_RCURLY","context":"normal","value":"}","line":14,"start":441,"end":442},{"type":"T_RPAREN","context":"normal","value":")","line":14,"start":442,"end":443},{"type":"T_IDENTIFIER","context":"normal","value":"doSomethingAsync","line":15,"start":448,"end":464},{"type":"T_LPAREN","context":"normal","value":"(","line":15,"start":464,"end":465},{"type":"T_IDENTIFIER","context":"normal","value":"baz","line":15,"start":465,"end":468},{"type":"T_RPAREN","context":"normal","value":")","line":15,"start":468,"end":469},{"type":"T_PERIOD","context":"normal","value":".","line":16,"start":476,"end":477},{"type":"T_IDENTIFIER","context":"normal","value":"then","line":16,"start":477,"end":481},{"type":"T_LPAREN","context":"normal","value":"(","line":16,"start":481,"end":482},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":16,"start":482,"end":487},{"type":"T_ARROW","context":"normal","value":"=>","line":16,"start":488,"end":490},{"type":"T_LCURLY","context":"normal","value":"{","line":16,"start":491,"end":492},{"type":"T_IDENTIFIER","context":"normal","value":"dispatch","line":17,"start":501,"end":509},{"type":"T_LPAREN","context":"normal","value":"(","line":17,"start":509,"end":510},{"type":"T_LCURLY","context":"normal","value":"{","line":17,"start":510,"end":511},{"type":"T_TYPE","context":"normal","value":"type","line":17,"start":512,"end":516},{"type":"T_COLON","context":"normal","value":":","line":17,"start":516,"end":517},{"type":"T_STRING","context":"normal","value":"\"FOO\"","line":17,"start":518,"end":523},{"type":"T_COMMA","context":"normal","value":",","line":17,"start":523,"end":524},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":17,"start":525,"end":528},{"type":"T_COLON","context":"normal","value":":","line":17,"start":528,"end":529},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":17,"start":530,"end":535},{"type":"T_RCURLY","context":"normal","value":"}","line":17,"start":536,"end":537},{"type":"T_RPAREN","context":"normal","value":")","line":17,"start":537,"end":538},{"type":"T_RCURLY","context":"normal","value":"}","line":18,"start":545,"end":546},{"type":"T_RPAREN","context":"normal","value":")","line":18,"start":546,"end":547},{"type":"T_RCURLY","context":"normal","value":"}","line":19,"start":552,"end":553},{"type":"T_RCURLY","context":"normal","value":"}","line":20,"start":554,"end":555}],"errors":[]}
Typing Redux reducers
Reducers take the state and
actions that we’ve typed and pulls them together for one method.
1
2
3
|
function reducer(state: State, action: Action): State {
}
|
{"value":"function reducer(state: State, action: Action): State {\n // ...\n}\n","tokens":[{"type":"T_FUNCTION","context":"normal","value":"function","line":1,"start":0,"end":8},{"type":"T_IDENTIFIER","context":"normal","value":"reducer","line":1,"start":9,"end":16},{"type":"T_LPAREN","context":"normal","value":"(","line":1,"start":16,"end":17},{"type":"T_IDENTIFIER","context":"normal","value":"state","line":1,"start":17,"end":22},{"type":"T_COLON","context":"type","value":":","line":1,"start":22,"end":23},{"type":"T_IDENTIFIER","context":"type","value":"State","line":1,"start":24,"end":29},{"type":"T_COMMA","context":"normal","value":",","line":1,"start":29,"end":30},{"type":"T_IDENTIFIER","context":"normal","value":"action","line":1,"start":31,"end":37},{"type":"T_COLON","context":"type","value":":","line":1,"start":37,"end":38},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":1,"start":39,"end":45},{"type":"T_RPAREN","context":"normal","value":")","line":1,"start":45,"end":46},{"type":"T_COLON","context":"type","value":":","line":1,"start":46,"end":47},{"type":"T_IDENTIFIER","context":"type","value":"State","line":1,"start":48,"end":53},{"type":"T_LCURLY","context":"normal","value":"{","line":1,"start":54,"end":55},{"type":"Line","context":"comment","value":"// ...","line":2,"start":58,"end":64},{"type":"T_RCURLY","context":"normal","value":"}","line":3,"start":65,"end":66}],"errors":[]}
You can also validate that you have handled every single type of action by
using the empty
type in your default
case.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
type State = { +value: boolean };
type FooAction = { type: "FOO", foo: boolean };
type BarAction = { type: "BAR", bar: boolean };
type Action = FooAction | BarAction;
function reducer(state: State, action: Action): State {
switch (action.type) {
case "FOO": return { ...state, value: action.foo };
case "BAR": return { ...state, value: action.bar };
default:
(action: empty);
return state;
}
}
|
{"value":"// @flow\ntype State = { +value: boolean };\n\ntype FooAction = { type: \"FOO\", foo: boolean };\ntype BarAction = { type: \"BAR\", bar: boolean };\n\ntype Action = FooAction | BarAction;\n\nfunction reducer(state: State, action: Action): State {\n switch (action.type) {\n case \"FOO\": return { ...state, value: action.foo };\n case \"BAR\": return { ...state, value: action.bar };\n default:\n (action: empty);\n return state;\n }\n}\n","tokens":[{"type":"Line","context":"comment","value":"// @flow","line":1,"start":0,"end":8},{"type":"T_TYPE","context":"normal","value":"type","line":2,"start":9,"end":13},{"type":"T_IDENTIFIER","context":"type","value":"State","line":2,"start":14,"end":19},{"type":"T_ASSIGN","context":"type","value":"=","line":2,"start":20,"end":21},{"type":"T_LCURLY","context":"type","value":"{","line":2,"start":22,"end":23},{"type":"T_PLUS","context":"type","value":"+","line":2,"start":24,"end":25},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":2,"start":25,"end":30},{"type":"T_COLON","context":"type","value":":","line":2,"start":30,"end":31},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":2,"start":32,"end":39},{"type":"T_RCURLY","context":"type","value":"}","line":2,"start":40,"end":41},{"type":"T_SEMICOLON","context":"normal","value":";","line":2,"start":41,"end":42},{"type":"T_TYPE","context":"normal","value":"type","line":4,"start":44,"end":48},{"type":"T_IDENTIFIER","context":"type","value":"FooAction","line":4,"start":49,"end":58},{"type":"T_ASSIGN","context":"type","value":"=","line":4,"start":59,"end":60},{"type":"T_LCURLY","context":"type","value":"{","line":4,"start":61,"end":62},{"type":"T_TYPE","context":"normal","value":"type","line":4,"start":63,"end":67},{"type":"T_COLON","context":"type","value":":","line":4,"start":67,"end":68},{"type":"T_STRING","context":"type","value":"\"FOO\"","line":4,"start":69,"end":74},{"type":"T_COMMA","context":"type","value":",","line":4,"start":74,"end":75},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":4,"start":76,"end":79},{"type":"T_COLON","context":"type","value":":","line":4,"start":79,"end":80},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":4,"start":81,"end":88},{"type":"T_RCURLY","context":"type","value":"}","line":4,"start":89,"end":90},{"type":"T_SEMICOLON","context":"normal","value":";","line":4,"start":90,"end":91},{"type":"T_TYPE","context":"normal","value":"type","line":5,"start":92,"end":96},{"type":"T_IDENTIFIER","context":"type","value":"BarAction","line":5,"start":97,"end":106},{"type":"T_ASSIGN","context":"type","value":"=","line":5,"start":107,"end":108},{"type":"T_LCURLY","context":"type","value":"{","line":5,"start":109,"end":110},{"type":"T_TYPE","context":"normal","value":"type","line":5,"start":111,"end":115},{"type":"T_COLON","context":"type","value":":","line":5,"start":115,"end":116},{"type":"T_STRING","context":"type","value":"\"BAR\"","line":5,"start":117,"end":122},{"type":"T_COMMA","context":"type","value":",","line":5,"start":122,"end":123},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":5,"start":124,"end":127},{"type":"T_COLON","context":"type","value":":","line":5,"start":127,"end":128},{"type":"T_BOOLEAN_TYPE","context":"type","value":"boolean","line":5,"start":129,"end":136},{"type":"T_RCURLY","context":"type","value":"}","line":5,"start":137,"end":138},{"type":"T_SEMICOLON","context":"normal","value":";","line":5,"start":138,"end":139},{"type":"T_TYPE","context":"normal","value":"type","line":7,"start":141,"end":145},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":7,"start":146,"end":152},{"type":"T_ASSIGN","context":"type","value":"=","line":7,"start":153,"end":154},{"type":"T_IDENTIFIER","context":"type","value":"FooAction","line":7,"start":155,"end":164},{"type":"T_BIT_OR","context":"type","value":"|","line":7,"start":165,"end":166},{"type":"T_IDENTIFIER","context":"type","value":"BarAction","line":7,"start":167,"end":176},{"type":"T_SEMICOLON","context":"normal","value":";","line":7,"start":176,"end":177},{"type":"T_FUNCTION","context":"normal","value":"function","line":9,"start":179,"end":187},{"type":"T_IDENTIFIER","context":"normal","value":"reducer","line":9,"start":188,"end":195},{"type":"T_LPAREN","context":"normal","value":"(","line":9,"start":195,"end":196},{"type":"T_IDENTIFIER","context":"normal","value":"state","line":9,"start":196,"end":201},{"type":"T_COLON","context":"type","value":":","line":9,"start":201,"end":202},{"type":"T_IDENTIFIER","context":"type","value":"State","line":9,"start":203,"end":208},{"type":"T_COMMA","context":"normal","value":",","line":9,"start":208,"end":209},{"type":"T_IDENTIFIER","context":"normal","value":"action","line":9,"start":210,"end":216},{"type":"T_COLON","context":"type","value":":","line":9,"start":216,"end":217},{"type":"T_IDENTIFIER","context":"type","value":"Action","line":9,"start":218,"end":224},{"type":"T_RPAREN","context":"normal","value":")","line":9,"start":224,"end":225},{"type":"T_COLON","context":"type","value":":","line":9,"start":225,"end":226},{"type":"T_IDENTIFIER","context":"type","value":"State","line":9,"start":227,"end":232},{"type":"T_LCURLY","context":"normal","value":"{","line":9,"start":233,"end":234},{"type":"T_SWITCH","context":"normal","value":"switch","line":10,"start":237,"end":243},{"type":"T_LPAREN","context":"normal","value":"(","line":10,"start":244,"end":245},{"type":"T_IDENTIFIER","context":"normal","value":"action","line":10,"start":245,"end":251},{"type":"T_PERIOD","context":"normal","value":".","line":10,"start":251,"end":252},{"type":"T_TYPE","context":"normal","value":"type","line":10,"start":252,"end":256},{"type":"T_RPAREN","context":"normal","value":")","line":10,"start":256,"end":257},{"type":"T_LCURLY","context":"normal","value":"{","line":10,"start":258,"end":259},{"type":"T_CASE","context":"normal","value":"case","line":11,"start":264,"end":268},{"type":"T_STRING","context":"normal","value":"\"FOO\"","line":11,"start":269,"end":274},{"type":"T_COLON","context":"normal","value":":","line":11,"start":274,"end":275},{"type":"T_RETURN","context":"normal","value":"return","line":11,"start":276,"end":282},{"type":"T_LCURLY","context":"normal","value":"{","line":11,"start":283,"end":284},{"type":"T_ELLIPSIS","context":"normal","value":"...","line":11,"start":285,"end":288},{"type":"T_IDENTIFIER","context":"normal","value":"state","line":11,"start":288,"end":293},{"type":"T_COMMA","context":"normal","value":",","line":11,"start":293,"end":294},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":11,"start":295,"end":300},{"type":"T_COLON","context":"normal","value":":","line":11,"start":300,"end":301},{"type":"T_IDENTIFIER","context":"normal","value":"action","line":11,"start":302,"end":308},{"type":"T_PERIOD","context":"normal","value":".","line":11,"start":308,"end":309},{"type":"T_IDENTIFIER","context":"normal","value":"foo","line":11,"start":309,"end":312},{"type":"T_RCURLY","context":"normal","value":"}","line":11,"start":313,"end":314},{"type":"T_SEMICOLON","context":"normal","value":";","line":11,"start":314,"end":315},{"type":"T_CASE","context":"normal","value":"case","line":12,"start":320,"end":324},{"type":"T_STRING","context":"normal","value":"\"BAR\"","line":12,"start":325,"end":330},{"type":"T_COLON","context":"normal","value":":","line":12,"start":330,"end":331},{"type":"T_RETURN","context":"normal","value":"return","line":12,"start":332,"end":338},{"type":"T_LCURLY","context":"normal","value":"{","line":12,"start":339,"end":340},{"type":"T_ELLIPSIS","context":"normal","value":"...","line":12,"start":341,"end":344},{"type":"T_IDENTIFIER","context":"normal","value":"state","line":12,"start":344,"end":349},{"type":"T_COMMA","context":"normal","value":",","line":12,"start":349,"end":350},{"type":"T_IDENTIFIER","context":"normal","value":"value","line":12,"start":351,"end":356},{"type":"T_COLON","context":"normal","value":":","line":12,"start":356,"end":357},{"type":"T_IDENTIFIER","context":"normal","value":"action","line":12,"start":358,"end":364},{"type":"T_PERIOD","context":"normal","value":".","line":12,"start":364,"end":365},{"type":"T_IDENTIFIER","context":"normal","value":"bar","line":12,"start":365,"end":368},{"type":"T_RCURLY","context":"normal","value":"}","line":12,"start":369,"end":370},{"type":"T_SEMICOLON","context":"normal","value":";","line":12,"start":370,"end":371},{"type":"T_DEFAULT","context":"normal","value":"default","line":13,"start":376,"end":383},{"type":"T_COLON","context":"normal","value":":","line":13,"start":383,"end":384},{"type":"T_LPAREN","context":"normal","value":"(","line":14,"start":391,"end":392},{"type":"T_IDENTIFIER","context":"normal","value":"action","line":14,"start":392,"end":398},{"type":"T_COLON","context":"type","value":":","line":14,"start":398,"end":399},{"type":"T_EMPTY_TYPE","context":"type","value":"empty","line":14,"start":400,"end":405},{"type":"T_RPAREN","context":"normal","value":")","line":14,"start":405,"end":406},{"type":"T_SEMICOLON","context":"normal","value":";","line":14,"start":406,"end":407},{"type":"T_RETURN","context":"normal","value":"return","line":15,"start":414,"end":420},{"type":"T_IDENTIFIER","context":"normal","value":"state","line":15,"start":421,"end":426},{"type":"T_SEMICOLON","context":"normal","value":";","line":15,"start":426,"end":427},{"type":"T_RCURLY","context":"normal","value":"}","line":16,"start":430,"end":431},{"type":"T_RCURLY","context":"normal","value":"}","line":17,"start":432,"end":433}],"errors":[]}
Flow + Redux resources