jfairbank / redux-saga-test-plan

Test Redux Saga with an easy plan.
http://redux-saga-test-plan.jeremyfairbank.com
MIT License
1.25k stars 127 forks source link

Unexpected typescript type error with expectSaga #378

Open Yupeng-li opened 2 years ago

Yupeng-li commented 2 years ago

Not all the generator functions pass the type check when using expectSaga. Sometimes unexpected type error is raised if the yields in the function are mixed by saga effects and normal generator functions.

// Example
import { expectSaga } from "redux-saga-test-plan";
import { select } from "redux-saga/effects";

function* dummyGenerator(name: string) {
  yield select();
  console.log(name);
}

function* dummySagaFn() {
  const name: string = yield select(); // Type the return value. Important to reproduce the issue
  yield dummyGenerator(name);
}

it("", async () => {
  expectSaga(dummySagaFn).withState({ name: "test-name" }).run(); // type error 
});

Sample code (line 15): https://codesandbox.io/s/cranky-resonance-47uuz?file=/src/demo.test.ts Typescript version: 4.5

// Source code

interface Iterator<T, TReturn = any, TNext = undefined> {
    // NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
    next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
    return?(value?: TReturn): IteratorResult<T, TReturn>;
    throw?(e?: any): IteratorResult<T, TReturn>;
}

interface IterableIterator<T> extends Iterator<T> {
    [Symbol.iterator](): IterableIterator<T>;
}

export type SagaType = (...params: any[]) => SagaIterator | IterableIterator<any>;

export const expectSaga: (<S extends SagaType>(
  generator: S,
  ...sagaArgs: Parameters<S>
) => ExpectApi) & { DEFAULT_TIMEOUT: number };

The issue is in SagaType. IterableIterator<any> extends Iterator<T>. The TNext is default to undefined. If we type one of the return values of yield statements (line 10 in the example), the error occurs.

Potential solution: Change SagaType to export type SagaType = (...params: any[]) => SagaIterator | Generator<any>;