diff --git a/etc/redux-toolkit.api.md b/etc/redux-toolkit.api.md index d0bd3cf298..5efefa73e2 100644 --- a/etc/redux-toolkit.api.md +++ b/etc/redux-toolkit.api.md @@ -129,7 +129,7 @@ export function createAction

(type: T): Payl export function createAction, T extends string = string>(type: T, prepareAction: PA): PayloadActionCreator['payload'], T, PA>; // @public (undocumented) -export function createAsyncThunk(typePrefix: string, payloadCreator: AsyncThunkPayloadCreator, options?: AsyncThunkOptions): AsyncThunk; +export function createAsyncThunk(typePrefix: string, payloadCreator: AsyncThunkPayloadCreator, options?: AsyncThunkOptions): AsyncThunk; // @public (undocumented) export function createEntityAdapter(options?: { diff --git a/src/createAsyncThunk.ts b/src/createAsyncThunk.ts index 0642e7a2bf..6568520ccb 100644 --- a/src/createAsyncThunk.ts +++ b/src/createAsyncThunk.ts @@ -173,6 +173,8 @@ type AsyncThunkActionCreator< ? () => AsyncThunkAction // argument contains void : [void] extends [ThunkArg] // make optional ? (arg?: ThunkArg) => AsyncThunkAction // argument contains undefined + : [ThunkArg] extends [OptionalUnknown] + ? (arg?: unknown) => AsyncThunkAction : [undefined] extends [ThunkArg] ? WithStrictNullChecks< // with strict nullChecks: make optional @@ -270,8 +272,28 @@ export type AsyncThunk< typePrefix: string } +const optionalUnknown = Symbol() +/* + * Since TypeScript 4.0, the following example will cause an error when checking + * JavaScript files (with allowJs & checkJs): +```js +const thunk = createAsyncThunk('', arg => {}) +thunk() +// @ts-expect-error Expected 0 arguments, but got 1.ts(2554) +thunk('something') +``` + * The only way around that without breaking too much explicit existing behaviour + * is this type "OptionalUnknown". + * On the flip side, using a payloadcreator without a defined argument, like +```ts +const thunk = createAsyncThunk('', () => {}) +``` + * will now generate a thunk that can optionally be called with any first argument + * opposed to a thunk that would not accept any argument before. + */ +type OptionalUnknown = { [optionalUnknown]: never } + /** - * * @param typePrefix * @param payloadCreator * @param options @@ -280,7 +302,7 @@ export type AsyncThunk< */ export function createAsyncThunk< Returned, - ThunkArg = void, + ThunkArg = OptionalUnknown, ThunkApiConfig extends AsyncThunkConfig = {} >( typePrefix: string, diff --git a/type-tests/files/createAsyncThunk.typetest.ts b/type-tests/files/createAsyncThunk.typetest.ts index c93c4dd2bd..0eb839e46a 100644 --- a/type-tests/files/createAsyncThunk.typetest.ts +++ b/type-tests/files/createAsyncThunk.typetest.ts @@ -213,7 +213,8 @@ const defaultDispatch = (() => {}) as ThunkDispatch<{}, any, AnyAction> { const asyncThunk = createAsyncThunk('test', () => 0) expectType<() => any>(asyncThunk) - // @ts-expect-error cannot be called with an argument + // we have to allow anything to be passed in in this case, to allow + // for compatibility with allowJs & checkJS asyncThunk(0 as any) }