Skip to content

Commit f95f656

Browse files
committed
Replace all Function references with AnyFunction
1 parent 0cde410 commit f95f656

10 files changed

+101
-50
lines changed

docs/api/actionCreatorMiddleware.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import reducer from './reducer'
5454
// Augment middleware to consider all functions with a static type property to be action creators
5555
const isActionCreator = (
5656
action: unknown,
57-
): action is Function & { type: unknown } =>
57+
): action is (...args: any) => any & { type: unknown } =>
5858
typeof action === 'function' && 'type' in action
5959

6060
const actionCreatorMiddleware = createActionCreatorInvariantMiddleware({

packages/toolkit/src/actionCreatorInvariantMiddleware.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
import type { Middleware } from 'redux'
22
import { isActionCreator as isRTKAction } from './createAction'
3+
import type { AnyFunction } from './tsHelpers'
34

45
export interface ActionCreatorInvariantMiddlewareOptions {
56
/**
67
* The function to identify whether a value is an action creator.
78
* The default checks for a function with a static type property and match method.
89
*/
9-
isActionCreator?: (action: unknown) => action is Function & { type?: unknown }
10+
isActionCreator?: (
11+
action: unknown,
12+
) => action is AnyFunction & { type?: unknown }
1013
}
1114

1215
export function getMessage(type?: unknown) {
1316
const splitType = type ? `${type}`.split('/') : []
1417
const actionName = splitType[splitType.length - 1] || 'actionCreator'
1518
return `Detected an action creator with type "${
1619
type || 'unknown'
17-
}" being dispatched.
20+
}" being dispatched.
1821
Make sure you're calling the action creator before dispatching, i.e. \`dispatch(${actionName}())\` instead of \`dispatch(${actionName})\`. This is necessary even if the action has no payload.`
1922
}
2023

packages/toolkit/src/createAction.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { isAction } from 'redux'
22
import type {
3-
IsUnknownOrNonInferrable,
3+
AnyFunction,
44
IfMaybeUndefined,
55
IfVoid,
66
IsAny,
7+
IsUnknownOrNonInferrable,
78
} from './tsHelpers'
89
import { hasMatchFunction } from './tsHelpers'
910

@@ -257,7 +258,7 @@ export function createAction<
257258
prepareAction: PA,
258259
): PayloadActionCreator<ReturnType<PA>['payload'], T, PA>
259260

260-
export function createAction(type: string, prepareAction?: Function): any {
261+
export function createAction(type: string, prepareAction?: AnyFunction): any {
261262
function actionCreator(...args: any[]) {
262263
if (prepareAction) {
263264
const prepared = prepareAction(...args)
@@ -290,7 +291,7 @@ export function createAction(type: string, prepareAction?: Function): any {
290291
*/
291292
export function isActionCreator(
292293
action: unknown,
293-
): action is BaseActionCreator<unknown, string> & Function {
294+
): action is BaseActionCreator<unknown, string> & AnyFunction {
294295
return (
295296
typeof action === 'function' &&
296297
'type' in action &&

packages/toolkit/src/createReducer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { produce as createNextState, isDraft, isDraftable } from 'immer'
33
import type { Action, Reducer, UnknownAction } from 'redux'
44
import type { ActionReducerMapBuilder } from './mapBuilders'
55
import { executeReducerBuilderCallback } from './mapBuilders'
6-
import type { NoInfer, TypeGuard } from './tsHelpers'
6+
import type { AnyFunction, NoInfer, TypeGuard } from './tsHelpers'
77
import { freezeDraftable } from './utils'
88

99
/**
@@ -63,7 +63,7 @@ export type CaseReducers<S, AS extends Actions> = {
6363
[T in keyof AS]: AS[T] extends Action ? CaseReducer<S, AS[T]> : void
6464
}
6565

66-
export type NotFunction<T> = T extends Function ? never : T
66+
export type NotFunction<T> = T extends AnyFunction ? never : T
6767

6868
function isStateFunction<S>(x: unknown): x is () => S {
6969
return typeof x === 'function'

packages/toolkit/src/createSlice.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import type {
2525
import { createReducer } from './createReducer'
2626
import type { ActionReducerMapBuilder, TypedActionCreator } from './mapBuilders'
2727
import { executeReducerBuilderCallback } from './mapBuilders'
28-
import type { Id, TypeGuard } from './tsHelpers'
28+
import type { AnyFunction, Id, TypeGuard } from './tsHelpers'
2929
import { getOrInsertComputed } from './utils'
3030

3131
const asyncThunkSymbol = /* @__PURE__ */ Symbol.for(
@@ -864,7 +864,7 @@ interface ReducerHandlingContext<State> {
864864
>
865865
sliceCaseReducersByType: Record<string, CaseReducer<State, any>>
866866
sliceMatchers: ActionMatcherDescriptionCollection<State>
867-
actionCreators: Record<string, Function>
867+
actionCreators: Record<string, AnyFunction>
868868
}
869869

870870
interface ReducerHandlingContextMethods<State> {
@@ -915,7 +915,7 @@ interface ReducerHandlingContextMethods<State> {
915915
*/
916916
exposeAction(
917917
name: string,
918-
actionCreator: Function,
918+
actionCreator: AnyFunction,
919919
): ReducerHandlingContextMethods<State>
920920
/**
921921
* Add a case reducer to be exposed under the final `slice.caseReducers` key.

packages/toolkit/src/devtoolsExtension.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Action, ActionCreator, StoreEnhancer } from 'redux'
22
import { compose } from 'redux'
3+
import type { AnyFunction } from './tsHelpers'
34

45
/**
56
* @public
@@ -223,7 +224,7 @@ export const composeWithDevTools: ComposeWithDevTools =
223224
: function () {
224225
if (arguments.length === 0) return undefined
225226
if (typeof arguments[0] === 'object') return compose
226-
return compose.apply(null, arguments as any as Function[])
227+
return compose.apply(null, arguments as any as AnyFunction[])
227228
}
228229

229230
/**

packages/toolkit/src/query/endpointDefinitions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Api } from '@reduxjs/toolkit/query'
2+
import type { AnyFunction } from '../tsHelpers'
23
import type {
34
BaseQueryApi,
45
BaseQueryArg,
@@ -1039,7 +1040,7 @@ export function calculateProvidedBy<ResultType, QueryArg, ErrorType, MetaType>(
10391040
return []
10401041
}
10411042

1042-
function isFunction<T>(t: T): t is Extract<T, Function> {
1043+
function isFunction<T>(t: T): t is Extract<T, AnyFunction> {
10431044
return typeof t === 'function'
10441045
}
10451046

packages/toolkit/src/tests/actionCreatorInvariantMiddleware.test.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import type { ActionCreatorInvariantMiddlewareOptions } from '@internal/actionCreatorInvariantMiddleware'
2-
import { getMessage } from '@internal/actionCreatorInvariantMiddleware'
3-
import { createActionCreatorInvariantMiddleware } from '@internal/actionCreatorInvariantMiddleware'
2+
import {
3+
createActionCreatorInvariantMiddleware,
4+
getMessage,
5+
} from '@internal/actionCreatorInvariantMiddleware'
46
import type { MiddlewareAPI } from '@reduxjs/toolkit'
57
import { createAction } from '@reduxjs/toolkit'
8+
import type { AnyFunction } from '../tsHelpers'
69

710
describe('createActionCreatorInvariantMiddleware', () => {
811
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
@@ -50,7 +53,7 @@ describe('createActionCreatorInvariantMiddleware', () => {
5053
it('allows passing a custom predicate', () => {
5154
let predicateCalled = false
5255
const testAction = makeActionTester({
53-
isActionCreator(action): action is Function {
56+
isActionCreator(action): action is AnyFunction {
5457
predicateCalled = true
5558
return false
5659
},

packages/toolkit/src/tests/createAsyncThunk.test-d.ts

Lines changed: 74 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { AsyncThunkDispatchConfig } from '@internal/createAsyncThunk'
12
import type { TSVersion } from '@phryneas/ts-version'
23
import type {
34
AsyncThunk,
@@ -14,9 +15,11 @@ import {
1415
} from '@reduxjs/toolkit'
1516
import type { AxiosError } from 'axios'
1617
import apiRequest from 'axios'
17-
import type { AsyncThunkDispatchConfig } from '@internal/createAsyncThunk'
18+
import type { AnyFunction, AnyNonNullishValue } from '../tsHelpers'
1819

19-
const defaultDispatch = (() => {}) as ThunkDispatch<{}, any, UnknownAction>
20+
const defaultDispatch = (() => {
21+
/* No-Op */
22+
}) as ThunkDispatch<AnyNonNullishValue, any, UnknownAction>
2023
const unknownAction = { type: 'foo' } as UnknownAction
2124

2225
describe('type tests', () => {
@@ -96,19 +99,17 @@ describe('type tests', () => {
9699
{ id: 'a', title: 'First' },
97100
]
98101

99-
const correctDispatch = (() => {}) as ThunkDispatch<
100-
BookModel[],
101-
{ userAPI: Function },
102-
UnknownAction
103-
>
102+
const correctDispatch = (() => {
103+
/* No-Op */
104+
}) as ThunkDispatch<BookModel[], { userAPI: AnyFunction }, UnknownAction>
104105

105106
// Verify that the the first type args to createAsyncThunk line up right
106107
const fetchBooksTAC = createAsyncThunk<
107108
BookModel[],
108109
number,
109110
{
110111
state: BooksState
111-
extra: { userAPI: Function }
112+
extra: { userAPI: AnyFunction }
112113
}
113114
>(
114115
'books/fetch',
@@ -119,7 +120,7 @@ describe('type tests', () => {
119120

120121
expectTypeOf(state).toEqualTypeOf<BookModel[]>()
121122

122-
expectTypeOf(extra).toEqualTypeOf<{ userAPI: Function }>()
123+
expectTypeOf(extra).toEqualTypeOf<{ userAPI: AnyFunction }>()
123124

124125
return fakeBooks
125126
},
@@ -160,7 +161,7 @@ describe('type tests', () => {
160161

161162
test('regression #1156: union return values fall back to allowing only single member', () => {
162163
const fn = createAsyncThunk('session/isAdmin', async () => {
163-
const response: boolean = false
164+
const response = false
164165
return response
165166
})
166167
})
@@ -493,15 +494,19 @@ describe('type tests', () => {
493494
return 'ret' as const
494495
})
495496

496-
expectTypeOf(thunk).toEqualTypeOf<AsyncThunk<'ret', void, {}>>()
497+
expectTypeOf(thunk).toEqualTypeOf<
498+
AsyncThunk<'ret', void, AnyNonNullishValue>
499+
>()
497500
})
498501

499502
test('createAsyncThunk without generics, accessing `api` does not break return type', () => {
500503
const thunk = createAsyncThunk('test', (_: void, api) => {
501504
return 'ret' as const
502505
})
503506

504-
expectTypeOf(thunk).toEqualTypeOf<AsyncThunk<'ret', void, {}>>()
507+
expectTypeOf(thunk).toEqualTypeOf<
508+
AsyncThunk<'ret', void, AnyNonNullishValue>
509+
>()
505510
})
506511

507512
test('createAsyncThunk rejectWithValue without generics: Expect correct return type', () => {
@@ -551,17 +556,26 @@ describe('type tests', () => {
551556
}
552557

553558
// has to stay on one line or type tests fail in older TS versions
554-
// prettier-ignore
555-
// @ts-expect-error
556-
const shouldFail = createAsyncThunk('without generics', () => {}, { serializeError: funkySerializeError })
559+
const shouldFail = createAsyncThunk(
560+
'without generics',
561+
() => {
562+
/* No-Op */
563+
},
564+
// @ts-expect-error
565+
{ serializeError: funkySerializeError },
566+
)
557567

558568
const shouldWork = createAsyncThunk<
559569
any,
560570
void,
561571
{ serializedErrorType: Funky }
562-
>('with generics', () => {}, {
563-
serializeError: funkySerializeError,
564-
})
572+
>(
573+
'with generics',
574+
() => {
575+
/* No-Op */
576+
},
577+
{ serializeError: funkySerializeError },
578+
)
565579

566580
if (shouldWork.rejected.match(unknownAction)) {
567581
expectTypeOf(unknownAction.error).toEqualTypeOf<Funky>()
@@ -571,33 +585,54 @@ describe('type tests', () => {
571585
test('`idGenerator` option takes no arguments, and returns a string', () => {
572586
const returnsNumWithArgs = (foo: any) => 100
573587
// has to stay on one line or type tests fail in older TS versions
574-
// prettier-ignore
575-
// @ts-expect-error
576-
const shouldFailNumWithArgs = createAsyncThunk('foo', () => {}, { idGenerator: returnsNumWithArgs })
588+
const shouldFailNumWithArgs = createAsyncThunk(
589+
'foo',
590+
() => {
591+
/* No-Op */
592+
},
593+
// @ts-expect-error
594+
{ idGenerator: returnsNumWithArgs },
595+
)
577596

578597
const returnsNumWithoutArgs = () => 100
579-
// prettier-ignore
580-
// @ts-expect-error
581-
const shouldFailNumWithoutArgs = createAsyncThunk('foo', () => {}, { idGenerator: returnsNumWithoutArgs })
598+
const shouldFailNumWithoutArgs = createAsyncThunk(
599+
'foo',
600+
() => {
601+
/* No-Op */
602+
},
603+
// @ts-expect-error
604+
{ idGenerator: returnsNumWithoutArgs },
605+
)
582606

583607
const returnsStrWithNumberArg = (foo: number) => 'foo'
584-
// prettier-ignore
585-
// @ts-expect-error
586-
const shouldFailWrongArgs = createAsyncThunk('foo', (arg: string) => {}, { idGenerator: returnsStrWithNumberArg })
608+
const shouldFailWrongArgs = createAsyncThunk(
609+
'foo',
610+
(arg: string) => {
611+
/* No-Op */
612+
},
613+
// @ts-expect-error
614+
{ idGenerator: returnsStrWithNumberArg },
615+
)
587616

588617
const returnsStrWithStringArg = (foo: string) => 'foo'
589618
const shoulducceedCorrectArgs = createAsyncThunk(
590619
'foo',
591-
(arg: string) => {},
620+
(arg: string) => {
621+
/* No-Op */
622+
},
592623
{
593624
idGenerator: returnsStrWithStringArg,
594625
},
595626
)
596627

597628
const returnsStrWithoutArgs = () => 'foo'
598-
const shouldSucceed = createAsyncThunk('foo', () => {}, {
599-
idGenerator: returnsStrWithoutArgs,
600-
})
629+
const shouldSucceed = createAsyncThunk(
630+
'foo',
631+
() => {
632+
/* No-Op */
633+
},
634+
{ idGenerator: returnsStrWithoutArgs },
635+
)
601636
})
602637

603638
test('fulfillWithValue should infer return value', () => {
@@ -633,8 +668,14 @@ describe('type tests', () => {
633668

634669
test('meta return values', () => {
635670
// return values
636-
createAsyncThunk<'ret', void, {}>('test', (_, api) => 'ret' as const)
637-
createAsyncThunk<'ret', void, {}>('test', async (_, api) => 'ret' as const)
671+
createAsyncThunk<'ret', void, AnyNonNullishValue>(
672+
'test',
673+
(_, api) => 'ret' as const,
674+
)
675+
createAsyncThunk<'ret', void, AnyNonNullishValue>(
676+
'test',
677+
async (_, api) => 'ret' as const,
678+
)
638679
createAsyncThunk<'ret', void, { fulfilledMeta: string }>('test', (_, api) =>
639680
api.fulfillWithValue('ret' as const, ''),
640681
)

packages/toolkit/src/tests/getDefaultMiddleware.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { thunk } from 'redux-thunk'
1010
import { vi } from 'vitest'
1111

1212
import { buildGetDefaultMiddleware } from '@internal/getDefaultMiddleware'
13+
import type { AnyFunction } from '../tsHelpers'
1314

1415
const getDefaultMiddleware = buildGetDefaultMiddleware()
1516

@@ -180,7 +181,7 @@ it('allows passing options to actionCreatorCheck', () => {
180181
immutableCheck: false,
181182
serializableCheck: false,
182183
actionCreatorCheck: {
183-
isActionCreator: (action: unknown): action is Function => {
184+
isActionCreator: (action: unknown): action is AnyFunction => {
184185
actionCreatorCheckWasCalled = true
185186
return false
186187
},

0 commit comments

Comments
 (0)