使用 Typescript 在 Redux-Saga 中键入生成器函数
Typing generator functions in Redux-Saga with Typescript
最近我开始重构我的 React 项目以开始在其中使用 Typescript。我遇到了打字问题,我不知道如何克服。
技术堆栈:Typescript、React、Redux、Redux-Saga
我也在使用带有 AirBnB 规则集的 ESLint。
我正在尝试编写一个 saga,它使用我的授权服务中定义的异步函数。下面的代码是我第二次尝试编写此代码。我已经拆分了 signIn saga,以免混合 yield return 类型,如 [=15= 末尾所建议的那样].
export function* callSignInService(userCredentials: UserCredentialsInterface):
Generator<CallEffect, UserAuthDataInterface, UserAuthDataInterface> >
{
return yield call(signInService, userCredentials);
}
export function* signIn(action: PayloadAction<UserCredentialsInterface>):
Generator<StrictEffect, void, PutEffect>
{
try {
const { payload } = action;
const userData = yield* callSignInService(payload);
yield put(signInSuccess(userData));
} catch (error) {
yield put(signInFailure(error.message));
}
}
登录服务的简化版本:
const signIn = async ( userCredentials: UserCredentialsInterface ): Promise<UserAuthDataInterface>
{
/* ... Some credential format validations ... */
try {
const response = await axios.post('someUrl', userCredentials);
return {
/* objectContent */
}: UserAuthDataInterface
} catch (error) {
throw new Error(AuthorizationErrorType.SERVER_ERROR);
}
}
问题是我仍然遇到错误:
const userData = yield* callSignInService(payload);
说:
TS2766: Cannot delegate iteration to value because the 'next' method of its iterator expects type 'UserAuthDataInterface', but the containing generator will always send 'PutEffect'. Type 'SimpleEffect<"PUT", PutEffectDescriptor>' is missing the following properties from type 'UserAuthDataInterface': user, token
我知道问题是我的 signIn 生成器 NextType 设置为 PutEffect它期望表达式 yield signInService(userCredentials)
到 return PutEffect 但这不是我的目标。
我想使用 signInService 获取 UserAuthData 然后将这些数据放入 signInSuccess 操作(signInSuccess 是使用 action creator 创建的)。
我已经阅读了一些关于如何正确键入生成器的资源,但仍然无法在我的示例中使用它。我发现 redux-saga 有或有关于打字的问题的信息,但我不确定在 2021 年是否仍然如此。
我是不是遗漏了一些明显的东西?也许我尝试编写这样的 Saga 有问题。如果有人可以看一下并给我建议如何处理这个问题,我将很高兴。
第一个泛型类型参数是传奇中 yield
ed 值的类型。换句话说,就是“步骤”。
将 callSignInService
移动到一个单独的函数实际上对类型没有帮助,因为我们仍在 yield
ing 该结果。
您的 signIn
saga 有两个不同类型的步骤 -- 调用 API 和调度一个动作。泛型需要是两种类型的联合。
export function* signIn(
action: PayloadAction<UserCredentialsInterface>
): Generator<
// step types
CallEffect<UserAuthDataInterface> | PutEffect<AnyAction>,
// return type
void,
// intermediate argument
UserAuthDataInterface
> {
try {
const { payload } = action;
const userData: UserAuthDataInterface = yield call(signInService, payload);
yield put(signInSuccess(userData));
} catch (error) {
yield put(signInFailure(error.message));
}
}
我假设您的设置需要 return 类型声明(否则这很容易!)。暂时删除声明以查看 Typescript 推断的内容真的很有帮助。这就是我得到这个解决方案的方式。
最近我开始重构我的 React 项目以开始在其中使用 Typescript。我遇到了打字问题,我不知道如何克服。
技术堆栈:Typescript、React、Redux、Redux-Saga
我也在使用带有 AirBnB 规则集的 ESLint。
我正在尝试编写一个 saga,它使用我的授权服务中定义的异步函数。下面的代码是我第二次尝试编写此代码。我已经拆分了 signIn saga,以免混合 yield return 类型,如 [=15= 末尾所建议的那样].
export function* callSignInService(userCredentials: UserCredentialsInterface):
Generator<CallEffect, UserAuthDataInterface, UserAuthDataInterface> >
{
return yield call(signInService, userCredentials);
}
export function* signIn(action: PayloadAction<UserCredentialsInterface>):
Generator<StrictEffect, void, PutEffect>
{
try {
const { payload } = action;
const userData = yield* callSignInService(payload);
yield put(signInSuccess(userData));
} catch (error) {
yield put(signInFailure(error.message));
}
}
登录服务的简化版本:
const signIn = async ( userCredentials: UserCredentialsInterface ): Promise<UserAuthDataInterface>
{
/* ... Some credential format validations ... */
try {
const response = await axios.post('someUrl', userCredentials);
return {
/* objectContent */
}: UserAuthDataInterface
} catch (error) {
throw new Error(AuthorizationErrorType.SERVER_ERROR);
}
}
问题是我仍然遇到错误:
const userData = yield* callSignInService(payload);
说:
TS2766: Cannot delegate iteration to value because the 'next' method of its iterator expects type 'UserAuthDataInterface', but the containing generator will always send 'PutEffect'. Type 'SimpleEffect<"PUT", PutEffectDescriptor>' is missing the following properties from type 'UserAuthDataInterface': user, token
我知道问题是我的 signIn 生成器 NextType 设置为 PutEffect它期望表达式 yield signInService(userCredentials)
到 return PutEffect 但这不是我的目标。
我想使用 signInService 获取 UserAuthData 然后将这些数据放入 signInSuccess 操作(signInSuccess 是使用 action creator 创建的)。
我已经阅读了一些关于如何正确键入生成器的资源,但仍然无法在我的示例中使用它。我发现 redux-saga 有或有关于打字的问题的信息,但我不确定在 2021 年是否仍然如此。
我是不是遗漏了一些明显的东西?也许我尝试编写这样的 Saga 有问题。如果有人可以看一下并给我建议如何处理这个问题,我将很高兴。
第一个泛型类型参数是传奇中 yield
ed 值的类型。换句话说,就是“步骤”。
将 callSignInService
移动到一个单独的函数实际上对类型没有帮助,因为我们仍在 yield
ing 该结果。
您的 signIn
saga 有两个不同类型的步骤 -- 调用 API 和调度一个动作。泛型需要是两种类型的联合。
export function* signIn(
action: PayloadAction<UserCredentialsInterface>
): Generator<
// step types
CallEffect<UserAuthDataInterface> | PutEffect<AnyAction>,
// return type
void,
// intermediate argument
UserAuthDataInterface
> {
try {
const { payload } = action;
const userData: UserAuthDataInterface = yield call(signInService, payload);
yield put(signInSuccess(userData));
} catch (error) {
yield put(signInFailure(error.message));
}
}
我假设您的设置需要 return 类型声明(否则这很容易!)。暂时删除声明以查看 Typescript 推断的内容真的很有帮助。这就是我得到这个解决方案的方式。