Skip to content

Commit

Permalink
use never instead of void for PayloadAction Meta & Error (#233)
Browse files Browse the repository at this point in the history
avoids `any` to take the `void` branch
fixes #224
  • Loading branch information
phryneas authored and markerikson committed Oct 31, 2019
1 parent 5ed8e48 commit 6f620fd
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
19 changes: 10 additions & 9 deletions src/createAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ import { IsUnknownOrNonInferrable } from './tsHelpers'
export type PayloadAction<
P = void,
T extends string = string,
M = void,
E = void
M = never,
E = never
> = WithOptional<M, E, WithPayload<P, Action<T>>>

export type PrepareAction<P> =
| ((...args: any[]) => { payload: P })
| ((...args: any[]) => { payload: P; meta: any })
| ((...args: any[]) => { payload: P; error: any })
| ((...args: any[]) => { payload: P; meta: any; error: any })

export type ActionCreatorWithPreparedPayload<
Expand All @@ -30,7 +31,7 @@ export type ActionCreatorWithPreparedPayload<
PA extends PrepareAction<infer P>
? (
...args: Parameters<PA>
) => PayloadAction<P, T, MetaOrVoid<PA>, ErrorOrVoid<PA>>
) => PayloadAction<P, T, MetaOrNever<PA>, ErrorOrNever<PA>>
: void
>

Expand Down Expand Up @@ -157,8 +158,8 @@ type Diff<T, U> = T extends U ? never : T
type WithPayload<P, T> = T & { payload: P }

type WithOptional<M, E, T> = T &
([M] extends [void] ? {} : { meta: M }) &
([E] extends [void] ? {} : { error: E })
([M] extends [never] ? {} : { meta: M }) &
([E] extends [never] ? {} : { error: E })

type WithTypeProperty<T, MergeIn> = {
type: T
Expand All @@ -170,17 +171,17 @@ type IfPrepareActionMethodProvided<
False
> = PA extends (...args: any[]) => any ? True : False

type MetaOrVoid<PA extends PrepareAction<any>> = ReturnType<PA> extends {
type MetaOrNever<PA extends PrepareAction<any>> = ReturnType<PA> extends {
meta: infer M
}
? M
: void
: never

type ErrorOrVoid<PA extends PrepareAction<any>> = ReturnType<PA> extends {
type ErrorOrNever<PA extends PrepareAction<any>> = ReturnType<PA> extends {
error: infer E
}
? E
: void
: never

type IfMaybeUndefined<P, True, False> = [undefined] extends [P] ? True : False

Expand Down
20 changes: 20 additions & 0 deletions type-tests/files/createAction.typetest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Action, AnyAction, ActionCreator } from 'redux'
import { createAction, PayloadAction, PayloadActionCreator } from '../../src'
import { IsAny } from 'src/tsHelpers'

function expectType<T>(p: T): T {
return p
Expand Down Expand Up @@ -218,4 +219,23 @@ function expectType<T>(p: T): T {
const u: number = action({input: ""}).payload.input;
// typings:expect-error
const v: number = action({input: 3}).payload.input;
}
/*
* regression test for https://github.com/reduxjs/redux-starter-kit/issues/224
*/
{
const oops = createAction('oops', (x: any) => ({ payload: x, error: x, meta: x }))

type Ret = ReturnType<typeof oops>;

const payload: IsAny<Ret['payload'], true, false> = true;
const error: IsAny<Ret['error'], true, false> = true;
const meta: IsAny<Ret['meta'], true, false> = true;

// typings:expect-error
const payloadNotAny: IsAny<Ret['payload'], true, false> = false;
// typings:expect-error
const errorNotAny: IsAny<Ret['error'], true, false> = false;
// typings:expect-error
const metaNotAny: IsAny<Ret['meta'], true, false> = false;
}

0 comments on commit 6f620fd

Please sign in to comment.