Navigation Menu

Skip to content

Commit

Permalink
Add some typings-tester tests
Browse files Browse the repository at this point in the history
  • Loading branch information
denisw committed Jan 8, 2019
1 parent 4ccb0e2 commit 60a9ddc
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 1 deletion.
1 change: 1 addition & 0 deletions index.d.ts
Expand Up @@ -5,6 +5,7 @@ export {
AnyAction,
Middleware,
Reducer,
Store,
StoreEnhancer
} from 'redux'
export { default as createSelector } from 'selectorator'
Expand Down
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -30,7 +30,8 @@
"rollup-plugin-babel": "^4.2.0",
"rollup-plugin-commonjs": "^9.2.0",
"rollup-plugin-node-resolve": "^4.0.0",
"typescript": "^3.2.2"
"typescript": "^3.2.2",
"typings-tester": "^0.3.2"
},
"scripts": {
"build": "rollup -c",
Expand Down
124 changes: 124 additions & 0 deletions type-tests/files/configureStore.typetest.ts
@@ -0,0 +1,124 @@
import { applyMiddleware } from 'redux'
import {
AnyAction,
configureStore,
Middleware,
PayloadAction,
Reducer,
Store
} from 'redux-starter-kit'

/*
* Test: configureStore() requires a valid reducer or reducer map.
*/
{
configureStore({
reducer: (state, action) => 0
})

configureStore({
reducer: {
counter1: () => 0,
counter2: () => 1
}
})

// typings:expect-error
configureStore({ reducer: 'not a reducer' })

// typings:expect-error
configureStore({ reducer: { a: 'not a reducer' } })

// typings:expect-error
configureStore({})
}

/*
* Test: configureStore() infers the store state type.
*/
{
const reducer: Reducer<number> = () => 0
const store = configureStore({ reducer })
const numberStore: Store<number, AnyAction> = store

// typings:expect-error
const stringStore: Store<string, AnyAction> = store
}

/*
* Test: configureStore() infers the store action type.
*/
{
const reducer: Reducer<number, PayloadAction<number>> = () => 0
const store = configureStore({ reducer })
const numberStore: Store<number, PayloadAction<number>> = store

// typings:expect-error
const stringStore: Store<number, PayloadAction<string>> = store
}

/*
* Test: configureStore() accepts middleware array.
*/
{
const middleware: Middleware = store => next => next

configureStore({
reducer: () => 0,
middleware: [middleware]
})

// typings:expect-error
configureStore({
reducer: () => 0,
middleware: ['not middleware']
})
}

/*
* Test: configureStore() accepts devTools flag.
*/
{
configureStore({
reducer: () => 0,
devTools: true
})

// typings:expect-error
configureStore({
reducer: () => 0,
devTools: 'true'
})
}

/*
* Test: configureStore() accepts preloadedState.
*/
{
configureStore({
reducer: () => 0,
preloadedState: 0
})

// typings:expect-error
configureStore({
reducer: () => 0,
preloadedState: 'non-matching state type'
})
}

/*
* Test: configureStore() accepts store enhancer.
*/
{
configureStore({
reducer: () => 0,
enhancers: [applyMiddleware(store => next => next)]
})

// typings:expect-error
configureStore({
reducer: () => 0,
enhancers: ['not a store enhancer']
})
}
114 changes: 114 additions & 0 deletions type-tests/files/createAction.typetest.ts
@@ -0,0 +1,114 @@
import {
createAction,
PayloadAction,
ActionCreator,
PayloadActionCreator,
Action,
AnyAction
} from 'redux-starter-kit'

/* PayloadAction */

/*
* Test: PayloadAction has type parameter for the payload.
*/
{
const action: PayloadAction<number> = { type: '', payload: 5 }
const numberPayload: number = action.payload

// typings:expect-error
const stringPayload: string = action.payload
}

/*
* Test: PayloadAction type parameter is optional (defaults to `any`).
*/
{
const action: PayloadAction = { type: '', payload: 5 }
const numberPayload: number = action.payload
const stringPayload: string = action.payload
}

/*
* Test: PayloadAction has a string type tag.
*/
{
const action: PayloadAction = { type: '', payload: 5 }

// typings:expect-error
const action2: PayloadAction = { type: 1, payload: 5 }
}

/*
* Test: PayloadAction is compatible with Action<string>
*/
{
const action: PayloadAction = { type: '', payload: 5 }
const stringAction: Action<string> = action
}

/* PayloadActionCreator */

/*
* Test: PayloadActionCreator returns Action or PayloadAction depending
* on whether a payload is passed.
*/
{
const actionCreator: PayloadActionCreator = (payload?: number) => ({
type: 'action',
payload
})

let action: Action
let payloadAction: PayloadAction

action = actionCreator()
action = actionCreator(1)
payloadAction = actionCreator(1)

// typings:expect-error
payloadAction = actionCreator()
}

/*
* Test: PayloadActionCreator is compatible with ActionCreator.
*/
{
const payloadActionCreator: PayloadActionCreator = (payload?: number) => ({
type: 'action',
payload
})
const actionCreator: ActionCreator<AnyAction> = payloadActionCreator

const payloadActionCreator2: PayloadActionCreator<number> = (
payload?: number
) => ({
type: 'action',
payload: payload || 1
})
const actionCreator2: ActionCreator<
PayloadAction<number>
> = payloadActionCreator2
}

/* createAction() */

/*
* Test: createAction() has type parameter for the action payload.
*/
{
const increment = createAction<number>('increment')
const n: number = increment(1).payload

// typings:expect-error
const s: string = increment(1).payload
}

/*
* Test: createAction() type parameter is optional (defaults to `any`).
*/
{
const increment = createAction('increment')
const n: number = increment(1).payload
const s: string = increment(1).payload
}
58 changes: 58 additions & 0 deletions type-tests/files/createReducer.typetest.ts
@@ -0,0 +1,58 @@
import { AnyAction, createReducer, Reducer } from 'redux-starter-kit'

/*
* Test: createReducer() infers type of returned reducer.
*/
{
type CounterAction =
| { type: 'increment'; payload: number }
| { type: 'decrement'; payload: number }

const incrementHandler = (state: number, action: CounterAction) => state + 1
const decrementHandler = (state: number, action: CounterAction) => state - 1

const reducer = createReducer(0 as number, {
increment: incrementHandler,
decrement: decrementHandler
})

const numberReducer: Reducer<number, CounterAction> = reducer

// typings:expect-error
const stringReducer: Reducer<string, CounterAction> = reducer

// typings:expect-error
const anyActionReducer: Reducer<number, AnyAction> = reducer
}

/**
* Test: createReducer() type parameters can be specified expliclity.
*/
{
type CounterAction =
| { type: 'increment'; payload: number }
| { type: 'decrement'; payload: number }

const incrementHandler = (state: number, action: CounterAction) =>
state + action.payload

const decrementHandler = (state: number, action: CounterAction) =>
state - action.payload

createReducer<number, CounterAction>(0, {
increment: incrementHandler,
decrement: decrementHandler
})

// typings:expect-error
createReducer<string, CounterAction>(0, {
increment: incrementHandler,
decrement: decrementHandler
})

// typings:expect-error
createReducer<number, AnyAction>(0, {
increment: incrementHandler,
decrement: decrementHandler
})
}
44 changes: 44 additions & 0 deletions type-tests/files/createSlice.typetest.ts
@@ -0,0 +1,44 @@
import {
AnyAction,
createSlice,
PayloadAction,
Reducer
} from 'redux-starter-kit'

/*
* Test: createSlice() infers the returned slice's type.
*/
{
const slice = createSlice({
slice: 'counter',
initialState: 0,
reducers: {
increment: (state: number, action) => state + action.payload,
decrement: (state: number, action) => state - action.payload
}
})

/* Reducer */

const reducer: Reducer<number, PayloadAction> = slice.reducer

// typings:expect-error
const stringReducer: Reducer<string, PayloadAction> = slice.reducer
// typings:expect-error
const anyActionReducer: Reducer<string, AnyAction> = slice.reducer

/* Actions */

slice.actions.increment(1)
slice.actions.decrement(1)

// typings:expect-error
slice.actions.other(1)

/* Selector */

const value: number = slice.selectors.getCounter(0)

// typings:expect-error
const stringValue: string = slice.selectors.getCounter(0)
}
11 changes: 11 additions & 0 deletions type-tests/files/tsconfig.json
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"lib": ["es2015"],
"strict": true,
"baseUrl": "../..",
"paths": {
"redux-starter-kit": ["index.d.ts"]
}
}
}
5 changes: 5 additions & 0 deletions type-tests/types.test.ts
@@ -0,0 +1,5 @@
import { checkDirectory } from 'typings-tester'

test('Types', () => {
checkDirectory(`${__dirname}/files`)
})

0 comments on commit 60a9ddc

Please sign in to comment.