Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strong typecheck for take*, throttle and debounce effects when action… #1984

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/red-cherries-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@redux-saga/core': patch
'@redux-saga/types': patch
---

Added strong typecheck for take\*, throttle and debounce effects if action type is provided
25 changes: 13 additions & 12 deletions packages/core/types/effects.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
Task,
StrictEffect,
ActionMatchingPattern,
ActionType,
} from '@redux-saga/types'

import { FlushableChannel, PuttableChannel, TakeableChannel } from './index'
Expand Down Expand Up @@ -74,7 +75,7 @@ export const effectTypes: {
* before terminating the Task.
*/
export function take(pattern?: ActionPattern): TakeEffect
export function take<A extends Action>(pattern?: ActionPattern<A>): TakeEffect
export function take<A extends Action<ActionType>>(pattern?: ActionPattern<A>): TakeEffect

/**
* Same as `take(pattern)` but does not automatically terminate the Saga on an
Expand All @@ -95,7 +96,7 @@ export function take<A extends Action>(pattern?: ActionPattern<A>): TakeEffect
* is getting closed when `dispatch(END)` happens
*/
export function takeMaybe(pattern?: ActionPattern): TakeEffect
export function takeMaybe<A extends Action>(pattern?: ActionPattern<A>): TakeEffect
export function takeMaybe<A extends Action<ActionType>>(pattern?: ActionPattern<A>): TakeEffect

export type TakeEffect = SimpleEffect<'TAKE', TakeEffectDescriptor>

Expand Down Expand Up @@ -185,8 +186,8 @@ export function takeEvery<P extends ActionPattern, Fn extends (...args: any[]) =
worker: Fn,
...args: HelperWorkerParameters<ActionMatchingPattern<P>, Fn>
): ForkEffect
export function takeEvery<A extends Action>(pattern: ActionPattern<A>, worker: (action: A) => any): ForkEffect
export function takeEvery<A extends Action, Fn extends (...args: any[]) => any>(
export function takeEvery<A extends Action<ActionType>>(pattern: ActionPattern<A>, worker: (action: A) => any): ForkEffect
export function takeEvery<A extends Action<ActionType>, Fn extends (...args: any[]) => any>(
pattern: ActionPattern<A>,
worker: Fn,
...args: HelperWorkerParameters<A, Fn>
Expand Down Expand Up @@ -263,8 +264,8 @@ export function takeLatest<P extends ActionPattern, Fn extends (...args: any[])
worker: Fn,
...args: HelperWorkerParameters<ActionMatchingPattern<P>, Fn>
): ForkEffect
export function takeLatest<A extends Action>(pattern: ActionPattern<A>, worker: (action: A) => any): ForkEffect
export function takeLatest<A extends Action, Fn extends (...args: any[]) => any>(
export function takeLatest<A extends Action<ActionType>>(pattern: ActionPattern<A>, worker: (action: A) => any): ForkEffect
export function takeLatest<A extends Action<ActionType>, Fn extends (...args: any[]) => any>(
pattern: ActionPattern<A>,
worker: Fn,
...args: HelperWorkerParameters<A, Fn>
Expand Down Expand Up @@ -335,8 +336,8 @@ export function takeLeading<P extends ActionPattern, Fn extends (...args: any[])
worker: Fn,
...args: HelperWorkerParameters<ActionMatchingPattern<P>, Fn>
): ForkEffect
export function takeLeading<A extends Action>(pattern: ActionPattern<A>, worker: (action: A) => any): ForkEffect
export function takeLeading<A extends Action, Fn extends (...args: any[]) => any>(
export function takeLeading<A extends Action<ActionType>>(pattern: ActionPattern<A>, worker: (action: A) => any): ForkEffect
export function takeLeading<A extends Action<ActionType>, Fn extends (...args: any[]) => any>(
pattern: ActionPattern<A>,
worker: Fn,
...args: HelperWorkerParameters<A, Fn>
Expand Down Expand Up @@ -1090,12 +1091,12 @@ export function throttle<P extends ActionPattern, Fn extends (...args: any[]) =>
worker: Fn,
...args: HelperWorkerParameters<ActionMatchingPattern<P>, Fn>
): ForkEffect
export function throttle<A extends Action>(
export function throttle<A extends Action<ActionType>>(
ms: number,
pattern: ActionPattern<A>,
worker: (action: A) => any,
): ForkEffect
export function throttle<A extends Action, Fn extends (...args: any[]) => any>(
export function throttle<A extends Action<ActionType>, Fn extends (...args: any[]) => any>(
ms: number,
pattern: ActionPattern<A>,
worker: Fn,
Expand Down Expand Up @@ -1181,12 +1182,12 @@ export function debounce<P extends ActionPattern, Fn extends (...args: any[]) =>
worker: Fn,
...args: HelperWorkerParameters<ActionMatchingPattern<P>, Fn>
): ForkEffect
export function debounce<A extends Action>(
export function debounce<A extends Action<ActionType>>(
ms: number,
pattern: ActionPattern<A>,
worker: (action: A) => any,
): ForkEffect
export function debounce<A extends Action, Fn extends (...args: any[]) => any>(
export function debounce<A extends Action<ActionType>, Fn extends (...args: any[]) => any>(
ms: number,
pattern: ActionPattern<A>,
worker: Fn,
Expand Down
59 changes: 48 additions & 11 deletions packages/core/types/effects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
debounce,
} from 'redux-saga/effects'
import { Action, ActionCreator } from 'redux'
import { StringableActionCreator, ActionMatchingPattern } from '@redux-saga/types'
import { StringableActionCreator, ActionMatchingPattern, ActionType } from '@redux-saga/types'

interface MyAction extends Action {
customField: string
Expand All @@ -53,6 +53,9 @@ declare const channel: Channel<ChannelItem>
declare const eventChannel: EventChannel<ChannelItem>
declare const multicastChannel: MulticastChannel<ChannelItem>

interface ACTION1 {type: 'ACTION1'}
const action1: ACTION1 = {type: 'ACTION1'}

function* testTake(): SagaIterator {
yield take()
yield take('my-action')
Expand All @@ -62,6 +65,10 @@ function* testTake(): SagaIterator {
// $ExpectError
yield take(() => {})

yield take<{type: 'ACTION1'}>('ACTION1')
// $ExpectError
yield take<{type: 'ACTION1'}>('ACTION2')

yield take(stringableActionCreator)

yield take(['my-action', (action: Action) => action.type === 'my-action', stringableActionCreator, isMyAction])
Expand Down Expand Up @@ -728,6 +735,12 @@ function* testTakeEvery(): SagaIterator {
// $ExpectError
yield takeEvery('my-action')

yield takeEvery<ACTION1>('ACTION1', (action: ACTION1) => {})
// $ExpectError
yield takeEvery<ACTION1>('ACTION2', (action: ACTION1) => {})
// $ExpectError
yield takeEvery<ACTION1>('ACTION1', (action: ACTION2) => {})

yield takeEvery('my-action', (action: Action) => {})
yield takeEvery('my-action', (action: MyAction) => {})
yield takeEvery('my-action', function*(action: Action): SagaIterator {})
Expand Down Expand Up @@ -785,7 +798,7 @@ function* testTakeEvery(): SagaIterator {
)

// $ExpectError
yield takeEvery(() => {}, (action: Action) => {})
yield takeEvery(() => {}, (action: Action<string>) => {})

yield takeEvery(stringableActionCreator, action => action.customField)

Expand Down Expand Up @@ -839,7 +852,7 @@ function* testChannelTakeEvery(): SagaIterator {
yield takeEvery(channel)

// $ExpectError
yield takeEvery(channel, (action: Action) => {})
yield takeEvery(channel, (action: Action<ActionType>) => {})
yield takeEvery(channel, (action: ChannelItem) => {})
yield takeEvery(channel, action => {
// $ExpectError
Expand Down Expand Up @@ -885,6 +898,12 @@ function* testTakeLatest(): SagaIterator {
// $ExpectError
yield takeLatest('my-action')

yield takeLatest<ACTION1>('ACTION1', (action: ACTION1) => {})
// $ExpectError
yield takeLatest<ACTION1>('ACTION2', (action: ACTION1) => {})
// $ExpectError
yield takeLatest<ACTION1>('ACTION1', (action: ACTION2) => {})

yield takeLatest('my-action', (action: Action) => {})
yield takeLatest('my-action', (action: MyAction) => {})
yield takeLatest('my-action', function*(action: Action): SagaIterator {})
Expand Down Expand Up @@ -934,7 +953,7 @@ function* testTakeLatest(): SagaIterator {
)

// $ExpectError
yield takeLatest(() => {}, (action: Action) => {})
yield takeLatest(() => {}, (action: Action<ActionType>) => {})

yield takeLatest(stringableActionCreator, action => action.customField)

Expand Down Expand Up @@ -988,7 +1007,7 @@ function* testChannelTakeLatest(): SagaIterator {
yield takeLatest(channel)

// $ExpectError
yield takeLatest(channel, (action: Action) => {})
yield takeLatest(channel, (action: Action<ActionType>) => {})
yield takeLatest(channel, (action: ChannelItem) => {})
yield takeLatest(channel, action => {
// $ExpectError
Expand Down Expand Up @@ -1034,6 +1053,12 @@ function* testTakeLeading(): SagaIterator {
// $ExpectError
yield takeLeading('my-action')

yield takeLeading<ACTION1>('ACTION1', (action: ACTION1) => {})
// $ExpectError
yield takeLeading<ACTION1>('ACTION2', (action: ACTION1) => {})
// $ExpectError
yield takeLeading<ACTION1>('ACTION1', (action: ACTION2) => {})

yield takeLeading('my-action', (action: Action) => {})
yield takeLeading('my-action', (action: MyAction) => {})
yield takeLeading('my-action', function*(action: Action): SagaIterator {})
Expand Down Expand Up @@ -1083,7 +1108,7 @@ function* testTakeLeading(): SagaIterator {
)

// $ExpectError
yield takeLeading(() => {}, (action: Action) => {})
yield takeLeading(() => {}, (action: Action<ActionType>) => {})

yield takeLeading(stringableActionCreator, action => action.customField)

Expand Down Expand Up @@ -1137,7 +1162,7 @@ function* testChannelTakeLeading(): SagaIterator {
yield takeLeading(channel)

// $ExpectError
yield takeLeading(channel, (action: Action) => {})
yield takeLeading(channel, (action: Action<ActionType>) => {})
yield takeLeading(channel, (action: ChannelItem) => {})
yield takeLeading(channel, action => {
// $ExpectError
Expand Down Expand Up @@ -1183,6 +1208,12 @@ function* testThrottle(): SagaIterator {
// $ExpectError
yield throttle(1, 'my-action')

yield throttle<ACTION1>(1, 'ACTION1', (action: ACTION1) => {})
// $ExpectError
yield throttle<ACTION1>(1, 'ACTION2', (action: ACTION1) => {})
// $ExpectError
yield throttle<ACTION1>(1, 'ACTION1', (action: ACTION2) => {})

yield throttle(1, 'my-action', (action: Action) => {})
yield throttle(1, 'my-action', (action: MyAction) => {})
yield throttle(1, 'my-action', function*(action: Action): SagaIterator {})
Expand Down Expand Up @@ -1233,7 +1264,7 @@ function* testThrottle(): SagaIterator {
)

// $ExpectError
yield throttle(1, () => {}, (action: Action) => {})
yield throttle(1, () => {}, (action: Action<ActionType>) => {})

yield throttle(1, stringableActionCreator, action => action.customField)

Expand Down Expand Up @@ -1290,7 +1321,7 @@ function* testChannelThrottle(): SagaIterator {
yield throttle(1, channel)

// $ExpectError
yield throttle(1, channel, (action: Action) => {})
yield throttle(1, channel, (action: Action<ActionType>) => {})
yield throttle(1, channel, (action: ChannelItem) => {})
yield throttle(1, channel, action => {
// $ExpectError
Expand Down Expand Up @@ -1336,6 +1367,12 @@ function* testDebounce(): SagaIterator {
// $ExpectError
yield debounce(1, 'my-action')

yield debounce<ACTION1>(1, 'ACTION1', (action: ACTION1) => {})
// $ExpectError
yield debounce<ACTION1>(1, 'ACTION2', (action: ACTION1) => {})
// $ExpectError
yield debounce<ACTION1>(1, 'ACTION1', (action: ACTION2) => {})

yield debounce(1, 'my-action', (action: Action) => {})
yield debounce(1, 'my-action', (action: MyAction) => {})
yield debounce(1, 'my-action', function*(action: Action): SagaIterator {})
Expand Down Expand Up @@ -1386,7 +1423,7 @@ function* testDebounce(): SagaIterator {
)

// $ExpectError
yield debounce(1, () => {}, (action: Action) => {})
yield debounce(1, () => {}, (action: Action<ActionType>) => {})

yield debounce(1, stringableActionCreator, action => action.customField)

Expand Down Expand Up @@ -1443,7 +1480,7 @@ function* testChannelDebounce(): SagaIterator {
yield debounce(1, channel)

// $ExpectError
yield debounce(1, channel, (action: Action) => {})
yield debounce(1, channel, (action: Action<ActionType>) => {})
yield debounce(1, channel, (action: ChannelItem) => {})
yield debounce(1, channel, action => {
// $ExpectError
Expand Down
25 changes: 13 additions & 12 deletions packages/core/types/ts3.6/effects.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
StrictEffect,
ActionMatchingPattern,
SagaIterator,
ActionType,
} from '@redux-saga/types'

import { FlushableChannel, PuttableChannel, TakeableChannel } from './index'
Expand Down Expand Up @@ -75,7 +76,7 @@ export const effectTypes: {
* before terminating the Task.
*/
export function take(pattern?: ActionPattern): TakeEffect
export function take<A extends Action>(pattern?: ActionPattern<A>): TakeEffect
export function take<A extends Action<ActionType>>(pattern?: ActionPattern<A>): TakeEffect

/**
* Same as `take(pattern)` but does not automatically terminate the Saga on an
Expand All @@ -96,7 +97,7 @@ export function take<A extends Action>(pattern?: ActionPattern<A>): TakeEffect
* is getting closed when `dispatch(END)` happens
*/
export function takeMaybe(pattern?: ActionPattern): TakeEffect
export function takeMaybe<A extends Action>(pattern?: ActionPattern<A>): TakeEffect
export function takeMaybe<A extends Action<ActionType>>(pattern?: ActionPattern<A>): TakeEffect

export type TakeEffect = SimpleEffect<'TAKE', TakeEffectDescriptor>

Expand Down Expand Up @@ -186,11 +187,11 @@ export function takeEvery<P extends ActionPattern, Fn extends (...args: any[]) =
worker: Fn,
...args: HelperWorkerParameters<ActionMatchingPattern<P>, Fn>
): ForkEffect<never>
export function takeEvery<A extends Action>(
export function takeEvery<A extends Action<ActionType>>(
pattern: ActionPattern<A>,
worker: (action: A) => any,
): ForkEffect<never>
export function takeEvery<A extends Action, Fn extends (...args: any[]) => any>(
export function takeEvery<A extends Action<ActionType>, Fn extends (...args: any[]) => any>(
pattern: ActionPattern<A>,
worker: Fn,
...args: HelperWorkerParameters<A, Fn>
Expand Down Expand Up @@ -270,11 +271,11 @@ export function takeLatest<P extends ActionPattern, Fn extends (...args: any[])
worker: Fn,
...args: HelperWorkerParameters<ActionMatchingPattern<P>, Fn>
): ForkEffect<never>
export function takeLatest<A extends Action>(
export function takeLatest<A extends Action<ActionType>>(
pattern: ActionPattern<A>,
worker: (action: A) => any,
): ForkEffect<never>
export function takeLatest<A extends Action, Fn extends (...args: any[]) => any>(
export function takeLatest<A extends Action<ActionType>, Fn extends (...args: any[]) => any>(
pattern: ActionPattern<A>,
worker: Fn,
...args: HelperWorkerParameters<A, Fn>
Expand Down Expand Up @@ -348,11 +349,11 @@ export function takeLeading<P extends ActionPattern, Fn extends (...args: any[])
worker: Fn,
...args: HelperWorkerParameters<ActionMatchingPattern<P>, Fn>
): ForkEffect<never>
export function takeLeading<A extends Action>(
export function takeLeading<A extends Action<ActionType>>(
pattern: ActionPattern<A>,
worker: (action: A) => any,
): ForkEffect<never>
export function takeLeading<A extends Action, Fn extends (...args: any[]) => any>(
export function takeLeading<A extends Action<ActionType>, Fn extends (...args: any[]) => any>(
pattern: ActionPattern<A>,
worker: Fn,
...args: HelperWorkerParameters<A, Fn>
Expand Down Expand Up @@ -1127,12 +1128,12 @@ export function throttle<P extends ActionPattern, Fn extends (...args: any[]) =>
worker: Fn,
...args: HelperWorkerParameters<ActionMatchingPattern<P>, Fn>
): ForkEffect<never>
export function throttle<A extends Action>(
export function throttle<A extends Action<ActionType>>(
ms: number,
pattern: ActionPattern<A>,
worker: (action: A) => any,
): ForkEffect<never>
export function throttle<A extends Action, Fn extends (...args: any[]) => any>(
export function throttle<A extends Action<ActionType>, Fn extends (...args: any[]) => any>(
ms: number,
pattern: ActionPattern<A>,
worker: Fn,
Expand Down Expand Up @@ -1222,12 +1223,12 @@ export function debounce<P extends ActionPattern, Fn extends (...args: any[]) =>
worker: Fn,
...args: HelperWorkerParameters<ActionMatchingPattern<P>, Fn>
): ForkEffect<never>
export function debounce<A extends Action>(
export function debounce<A extends Action<ActionType>>(
ms: number,
pattern: ActionPattern<A>,
worker: (action: A) => any,
): ForkEffect<never>
export function debounce<A extends Action, Fn extends (...args: any[]) => any>(
export function debounce<A extends Action<ActionType>, Fn extends (...args: any[]) => any>(
ms: number,
pattern: ActionPattern<A>,
worker: Fn,
Expand Down
Loading