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

Errors with TypeScript 3.7.2 #323

Open madandrija opened 4 years ago

madandrija commented 4 years ago

After upgrading to TS 3.7.2, I started to get the following error types (for all of them I assume that TS before the update couldn't properly check the functions which now throw errors):

  1. return expectSaga(watchForPostRequests) - TS complains that watchForPostRequests is not assignable to expectSaga since it expects an IterableIterator and I'm passing in a Generator. The reason this is a bug is because the examples in the documentation are examples of a Generator - I assume before this update
  2. .then(result => { - TS complains that result implicitly has any type - it should be RunResult
  3. .provide({ take(effect, next) { - TS complains that effect and next implicitly have any type - these should be effect: E.TakeEffectDescriptor & E.ChannelTakeEffectDescriptor<any> and next: ProviderNextF
madandrija commented 4 years ago

Just realised only sometimes I get incorrect typings, so since the code is working 😁 I assume typings are incorrect. Points two and three happen in any place, point one happens when functions are declared in a certain way:

export function* watchAppStateChange() {
  const stateChannel: Channel<AppStateType> = yield call(appStateChannel);
  const appsFlyerDisableInstallEventsListener = appsFlyer.onInstallConversionData((data: any) => {
    put(actionTrackAppsFlyerInstallConversion(data));
  });

  const appsFlyerDisableAtributionEventsListener = appsFlyer.onAppOpenAttribution((data: any) => {
    put(actionTrackAppsFlyerOpenAttribution(data));
  });

  while (true) {
    const state: AppStateType = yield take(stateChannel);

    switch (state) {
      case "active":
        if (Platform.OS === "ios") {
          appsFlyer.trackAppLaunch();
        }
        yield put(appStateChangedAction(state));
        break;
      case "inactive":
      case "background":
        yield put(appStateChangedAction(state));
        if (appsFlyerDisableInstallEventsListener) {
          appsFlyerDisableInstallEventsListener();
        }
        if (appsFlyerDisableAtributionEventsListener) {
          appsFlyerDisableAtributionEventsListener();
        }
        break;
      default:
        throw new Error("assertState - invalid type");
    }
  }
}
export function* exerciseUpdater() {
  while (true) {
    yield take((action: ReduxAction) => actionShouldTriggerExerciseUpdate(action));
    const exercisesFromDb: IExerciseReduxModel = yield select(getExercises);
    const exercisesFromDbAreValid = exerciseModelIsValid(exercisesFromDb);
    if (!exercisesFromDbAreValid) {
      const exercisesFromDisk = yield call(loadExercisesFromDisk);
      const exercisesFromDiskAreValid = exerciseModelIsValid(exercisesFromDisk);

      if (exercisesFromDiskAreValid) {
        yield put(exercisesLoadSuccessAction(exercisesFromDisk));
      }
    }
    const lastTimeExercisesUpdated = yield select(getExercisesLastTimeUpdated);

    yield put(getExercisesFromServerAction(lastTimeExercisesUpdated));
  }
}
export function* serverPingerWatcher() {
  while (true) {
    yield take(OFFLINE);
    const serverPingerTask: Task = yield call(serverPinger);
    yield take(ONLINE);
    if (serverPingerTask && serverPingerTask.isRunning()) {
      serverPingerTask.cancel();
    }
  }
}
export function* doGenerateElapsedTimeEvents(generateElapsedTime: () => number) {
  const elapsedTimeChannel: Channel<number> = yield call(timerChannel, generateElapsedTime);

  while (true) {
    try {
      const elapsedTime = yield take(elapsedTimeChannel);
      yield put(timeElapsed(elapsedTime));
    } finally {
      if (yield cancelled()) {
        elapsedTimeChannel.close();
      }
    }
  }
}