Reputation: 3806
I am learning about generators and redux-saga. I have taken from an existing example which uses yield*. The first method - yieldPromiseResponse using 'yield' is ok. The second method - watchPromise which yields the result of yieldPromiseResponse using yield* errors with
Error: Type 'ForkEffect' must have a 'Symbol.iterator' method that returns an Iterator
Can someone advise me what type to apply to this example?
const at: TAt = {
SUCCESS: 'SUCCESS',
};
interface Props {
username: string;
}
interface GProps {
payload: Props;
}
type Tprom = (payload: Props) => Promise<string>;
const prom: Tprom = username =>
new Promise((resolve, reject) => {
resolve(`resolve prom uesrname = ${username}`);
});
function* yieldPromiseResponse({ payload }: GProps) {
/* eslint-disable no-useless-catch */
try {
const user = yield call(prom, payload);
console.log('user = ', user);
yield put({ type: at.SUCCESS, user });
} catch (error) {
throw error;
}
}
function* watchPromise() {
yield* takeLatest(at.REQUEST, yieldPromiseResponse);
}
export default watchPromise;
Upvotes: 0
Views: 1383
Reputation: 3806
There are 2 problems here. The first one I have managed to fix.
yield takeLatest.
This causes new error:
No overload matches this call. The last overload gave the following error. Argument of type 'string' is not assignable to parameter of type 'TakeableChannel'.
This is because typescript thinks I'm using takeLatest as channel, not as pattern. https://redux-saga.js.org/docs/api/
Found the answer for the fix here: https://github.com/redux-saga/redux-saga/issues/1286
Updated code is now recognised in typescript without error
import { put, call, takeLatest } from 'redux-saga/effects';
import { Action } from 'redux';
const ActionTypeRequest = 'REQUEST';
interface Props {
username: string;
}
interface ActionResult<T> extends Action<string> {
type: string;
payload?: T;
}
type Tprom = (payload: Props) => Promise<string>;
const prom: Tprom = payload =>
new Promise((resolve, reject) => {
resolve(`resolve prom uesrname = ${payload.username}`);
});
function* yieldPromiseResponse(action: ActionResult<Props>) {
/* eslint-disable no-useless-catch */
const { payload } = action;
try {
const user = yield call(prom, payload as Props);
yield put({ type: ActionTypeRequest, user });
} catch (error) {
throw error;
}
}
function* watchPromise() {
yield takeLatest(ActionTypeRequest, yieldPromiseResponse);
}
export default watchPromise;
Problem 2 Still does not work with
yield* takeLatest(ActionTypeRequest, yieldPromiseResponse);
Maybe I need to understand the yield delegation - yield * When reading this - https://tech.lalilo.com/redux-saga-and-typescript-doing-it-right
When I change my code to this it does not complain. So maybe someone might be able to explain what is wrong with yield* on my takeLatest method.
function* secondaryGenerator() {
yield delay(111);
return true;
}
function* watchPromise() {
yield takeLatest(ActionTypeRequest, yieldPromiseResponse);
const secondary = yield* secondaryGenerator();
console.log('second = ', secondary);
}
Upvotes: 3