Skip to content

Commit b27f404

Browse files
phryneasmarkerikson
authored andcommitted
rename to withTypes, allow merge-overriding
1 parent 17befa6 commit b27f404

File tree

2 files changed

+63
-31
lines changed

2 files changed

+63
-31
lines changed

packages/toolkit/src/tests/createAsyncThunk.typetest.ts

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ import type { ThunkDispatch } from 'redux-thunk'
1212
import type { AxiosError } from 'axios'
1313
import apiRequest from 'axios'
1414
import type { IsAny, IsUnknown } from '@internal/tsHelpers'
15-
import { expectType } from './helpers'
15+
import { expectExactType, expectType } from './helpers'
1616
import type {
1717
AsyncThunkFulfilledActionCreator,
1818
AsyncThunkRejectedActionCreator,
1919
} from '@internal/createAsyncThunk'
2020

21+
const ANY = {} as any
2122
const defaultDispatch = (() => {}) as ThunkDispatch<{}, any, AnyAction>
2223
const anyAction = { type: 'foo' } as AnyAction
2324

@@ -598,53 +599,74 @@ const anyAction = { type: 'foo' } as AnyAction
598599
}
599600

600601
{
601-
const typedCAT = createAsyncThunk.forTypes<{
602+
const typedCAT = createAsyncThunk.withTypes<{
602603
state: RootState
603604
dispatch: AppDispatch
605+
rejectValue: string
604606
}>()
605607

608+
// inferred usage
606609
const thunk = typedCAT('foo', (arg: number, api) => {
607610
// correct getState Type
608611
const test1: number = api.getState().foo.value
609612
// correct dispatch type
610-
const test2: number = api.dispatch(
611-
(dispatch, getState) => getState().foo.value
612-
)
613+
const test2: number = api.dispatch((dispatch, getState) => {
614+
expectExactType<
615+
ThunkDispatch<{ foo: { value: number } }, undefined, AnyAction>
616+
>(ANY)(dispatch)
617+
expectExactType<() => { foo: { value: number } }>(ANY)(getState)
618+
return getState().foo.value
619+
})
620+
621+
if (1 < 2)
622+
// @ts-expect-error
623+
return api.rejectWithValue(5)
624+
if (1 < 2) return api.rejectWithValue('test')
613625
return test1 + test2
614626
})
615627

628+
// usage with two generics
616629
const thunk2 = typedCAT<number, string>('foo', (arg, api) => {
630+
expectExactType('' as string)(arg)
617631
// correct getState Type
618632
const test1: number = api.getState().foo.value
619633
// correct dispatch type
620-
const test2: number = api.dispatch(
621-
(dispatch, getState) => getState().foo.value
622-
)
634+
const test2: number = api.dispatch((dispatch, getState) => {
635+
expectExactType<
636+
ThunkDispatch<{ foo: { value: number } }, undefined, AnyAction>
637+
>(ANY)(dispatch)
638+
expectExactType<() => { foo: { value: number } }>(ANY)(getState)
639+
return getState().foo.value
640+
})
641+
if (1 < 2)
642+
// @ts-expect-error
643+
return api.rejectWithValue(5)
644+
if (1 < 2) return api.rejectWithValue('test')
623645
return test1 + test2
624646
})
625647

626-
const thunk3 = typedCAT<
627-
number,
628-
string,
629-
// @ts-expect-error TODO
630-
// right now this still errors because
631-
// it does not contain `state` and `dispatch`
632-
{
633-
rejectValue: string
634-
}
635-
>('foo', (arg, api) => {
636-
// correct getState Type
637-
const test1: number = api.getState().foo.value
638-
// correct dispatch type
639-
const test2: number = api.dispatch(
640-
(dispatch, getState) => getState().foo.value
641-
)
642-
if (1 < 2) {
643-
// TODO: @ts-expect-error
644-
return api.rejectWithValue(5)
648+
// usage with config override generic
649+
const thunk3 = typedCAT<number, string, { rejectValue: number }>(
650+
'foo',
651+
(arg, api) => {
652+
expectExactType('' as string)(arg)
653+
// correct getState Type
654+
const test1: number = api.getState().foo.value
655+
// correct dispatch type
656+
const test2: number = api.dispatch((dispatch, getState) => {
657+
expectExactType<
658+
ThunkDispatch<{ foo: { value: number } }, undefined, AnyAction>
659+
>(ANY)(dispatch)
660+
expectExactType<() => { foo: { value: number } }>(ANY)(getState)
661+
return getState().foo.value
662+
})
663+
if (1 < 2) return api.rejectWithValue(5)
664+
if (1 < 2)
665+
// @ts-expect-error
666+
return api.rejectWithValue('test')
667+
return 5
645668
}
646-
return api.rejectWithValue(5)
647-
})
669+
)
648670

649671
const slice = createSlice({
650672
name: 'foo',
@@ -655,13 +677,21 @@ const anyAction = { type: 'foo' } as AnyAction
655677
.addCase(thunk.fulfilled, (state, action) => {
656678
state.value += action.payload
657679
})
680+
.addCase(thunk.rejected, (state, action) => {
681+
expectExactType('' as string | undefined)(action.payload)
682+
})
658683
.addCase(thunk2.fulfilled, (state, action) => {
659684
state.value += action.payload
660685
})
661-
.addCase(thunk3.rejected, (state, action) => {
662-
// @ts-expect-error TODO does not have the right type yet because the config was incomplete
686+
.addCase(thunk2.rejected, (state, action) => {
687+
expectExactType('' as string | undefined)(action.payload)
688+
})
689+
.addCase(thunk3.fulfilled, (state, action) => {
663690
state.value += action.payload
664691
})
692+
.addCase(thunk3.rejected, (state, action) => {
693+
expectExactType(0 as number | undefined)(action.payload)
694+
})
665695
},
666696
})
667697

packages/toolkit/src/tsHelpers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,5 @@ export type ActionFromMatcher<M extends Matcher<any>> = M extends Matcher<
139139
>
140140
? T
141141
: never
142+
143+
export type Id<T> = { [K in keyof T]: T[K] } & {}

0 commit comments

Comments
 (0)