Skip to content

Instantly share code, notes, and snippets.

@deskoh
Last active May 25, 2019 04:16
Show Gist options
  • Save deskoh/b2990583f547871962d465f34b835291 to your computer and use it in GitHub Desktop.
Save deskoh/b2990583f547871962d465f34b835291 to your computer and use it in GitHub Desktop.
Redux Typings
export const ADD_TODO = 'ADD_TODO' as const
export const TOGGLE_TODO = 'TOGGLE_TODO' as const
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER' as const
/*
* other constants
*/
export const VisibilityFilters = {
SHOW_ALL: 'SHOW_ALL' as const,
SHOW_COMPLETED: 'SHOW_COMPLETED' as const,
SHOW_ACTIVE: 'SHOW_ACTIVE' as const,
}
/*
* action creators
*/
export function addTodo(text: string) {
return { type: ADD_TODO, text }
}
export function toggleTodo(index: number) {
return { type: TOGGLE_TODO, index }
}
export function setVisibilityFilter(filter: keyof typeof VisibilityFilters) {
return { type: SET_VISIBILITY_FILTER, filter }
}
export type TodoActionTypes =
ReturnType<typeof addTodo> |
ReturnType<typeof toggleTodo>
export type VisibilityActionTypes =
ReturnType<typeof setVisibilityFilter>
import { combineReducers, Reducer } from 'redux'
import {
ADD_TODO,
TOGGLE_TODO,
SET_VISIBILITY_FILTER,
VisibilityFilters,
VisibilityActionTypes,
TodoActionTypes
} from './actions'
const { SHOW_ALL } = VisibilityFilters
export type Todo = {
text: string
completed: boolean
}
type FilterTypes = keyof typeof VisibilityFilters;
const visibilityFilter: Reducer<FilterTypes, VisibilityActionTypes> = function (state = SHOW_ALL, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return action.filter
default:
return state
}
}
const todos: Reducer<Todo[], TodoActionTypes> = function (state = [], action) {
switch (action.type) {
case ADD_TODO:
return [
...state,
{
text: action.text,
completed: false
}
]
case TOGGLE_TODO:
return state.map((todo, index) => {
if (index === action.index) {
return Object.assign({}, todo, {
completed: !todo.completed
})
}
return todo
})
default:
return state
}
}
const todoApp = combineReducers({
visibilityFilter,
todos
})
export type AppState = ReturnType<typeof todoApp>
export default todoApp
import { connect } from 'react-redux'
import { toggleTodo, TodoActionTypes } from './actions'
import { VisibilityFilters } from './actions'
import { AppState } from './reducers';
import { Dispatch } from 'react';
type StateProps = ReturnType<typeof mapStateToProps>
type DispatchProps = ReturnType<typeof mapDispatchToProps>
type Props = StateProps & DispatchProps
const TodoList: React.FC<Props> = (props) => (
<ul>
{props}
</ul>
);
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case VisibilityFilters.SHOW_ALL:
return todos
case VisibilityFilters.SHOW_COMPLETED:
return todos.filter(t => t.completed)
case VisibilityFilters.SHOW_ACTIVE:
return todos.filter(t => !t.completed)
default:
throw new Error('Unknown filter: ' + filter)
}
}
const mapStateToProps = (state: AppState) => ({
todos: getVisibleTodos(state.todos, state.visibilityFilter)
})
const mapDispatchToProps = (dispatch: Dispatch<TodoActionTypes>) => ({
toggleTodo: (id: number) => dispatch(toggleTodo(id))
})
const ConnectedTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
// Object Shorthand for mapDispatchToProps
type DispatchObjectProps<T> = {
[P in keyof T]: (...a: T[P] extends (...args: infer U ) => any ? U: never) => void
}
type DispatchObjProps = DispatchObjectProps<typeof mapDispatchToObj>
const mapDispatchToObj = {
toggleTodo
}
export default ConnectedTodoList;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment