redux-saga "call" 影响没有正确输入 saga 参数
redux-saga "call" effect not typing saga params correctly
我有一个 saga 定义如下:
type GenericFunction = (...args: any[]) => any;
interface IFetchSaga<T extends GenericFunction> {
saga: T,
args: Parameters<T>
}
function* triggerChange<T extends GenericFunction>(fetchSaga: IFetchSaga<T>, shouldFetch: boolean) {
// ...do stuff
if(shouldFetch) {
yield call(fetchSaga.saga, ...fetchSaga.args);
}
// ...do stuff
}
当我尝试在另一个传奇中使用这个传奇时,使用 call
效果我没有得到 IFetchSaga
args 的正确输入:
function* fetchData(id: number, date: string) {
// ...do fetch
}
function* load() {
// ...do stuff
yield call(triggerChange, {
saga: fetchData,
args: ['10', '2021-03-22'] // I don't get an error saying that '10' should be a number
},
true
);
}
例如,当我尝试直接执行它时(就像它是任何其他函数一样),输入正确:
triggerChange({
saga: fetchData,
args: ['10', '2021-03-22'] // Here I get the error saying that '10' should be a number
});
在调用我的 saga 时,我能做些什么来正确输入 args 吗?
Ps.: 我知道我可以在调用效果之外定义我的 fetchSaga
参数,但是我必须总是用 [=19= 调用 IFetchSaga
](我想避免它):
function* fetchData(id: number, date: string) {
// ...do fetch
}
function* load() {
// ...do stuff
// This would work, but I want to avoid having to do it
const fetchSaga: IFetchSaga<typeof fetchData> = {
saga: fetchData,
args: ['10', '2021-03-22'] // Get the typing error for '10'
};
yield call(triggerChange, fetchSaga, true);
}
解决方案
我的建议是通过辅助函数创建 IFetchSaga<T>
对象。
function fetchable<T extends GenericFunction>( saga: T, ...args: Parameters<T>): IFetchSaga<T> {
return {saga, args};
}
如果需要,您可以将参数作为数组传递。
这允许 typescript 轻松推断函数的正确参数并确保它们匹配。
function* load() {
// error: Argument of type 'string' is not assignable to parameter of type 'number'
yield call(triggerChange, fetchable(fetchData, "10", "2021-03-22"), true);
// okay :)
yield call(triggerChange, fetchable(fetchData, 10, "2021-03-22"), true);
}
问题
原始版本失败的原因与 相似,我在其中进行了更深入的探讨。 triggerChange
是一个通用函数,可以用任何 T
调用。当我们为 triggerChange
创建 call
效果时,它不需要任何特定的 T
类型,因为 T
是在调用函数时确定的。参数的类型回落到 GenericFunction
,其中 args
是 any[]
,因此将数组分配给它没有问题。
我们的解决方案有效,因为我们通过直接调用 fetchable
来推断特定的 T
。给我们错误的是 fetchable
函数,而不是 call
。如果我们要声明 fetchable
T
只是 GenericFunction
那么我们将遇到与以前相同的问题。
// no errors, even though we want them
yield call(triggerChange, fetchable<GenericFunction>(fetchData, "10", "2021-03-22"), true);
我有一个 saga 定义如下:
type GenericFunction = (...args: any[]) => any;
interface IFetchSaga<T extends GenericFunction> {
saga: T,
args: Parameters<T>
}
function* triggerChange<T extends GenericFunction>(fetchSaga: IFetchSaga<T>, shouldFetch: boolean) {
// ...do stuff
if(shouldFetch) {
yield call(fetchSaga.saga, ...fetchSaga.args);
}
// ...do stuff
}
当我尝试在另一个传奇中使用这个传奇时,使用 call
效果我没有得到 IFetchSaga
args 的正确输入:
function* fetchData(id: number, date: string) {
// ...do fetch
}
function* load() {
// ...do stuff
yield call(triggerChange, {
saga: fetchData,
args: ['10', '2021-03-22'] // I don't get an error saying that '10' should be a number
},
true
);
}
例如,当我尝试直接执行它时(就像它是任何其他函数一样),输入正确:
triggerChange({
saga: fetchData,
args: ['10', '2021-03-22'] // Here I get the error saying that '10' should be a number
});
在调用我的 saga 时,我能做些什么来正确输入 args 吗?
Ps.: 我知道我可以在调用效果之外定义我的 fetchSaga
参数,但是我必须总是用 [=19= 调用 IFetchSaga
](我想避免它):
function* fetchData(id: number, date: string) {
// ...do fetch
}
function* load() {
// ...do stuff
// This would work, but I want to avoid having to do it
const fetchSaga: IFetchSaga<typeof fetchData> = {
saga: fetchData,
args: ['10', '2021-03-22'] // Get the typing error for '10'
};
yield call(triggerChange, fetchSaga, true);
}
解决方案
我的建议是通过辅助函数创建 IFetchSaga<T>
对象。
function fetchable<T extends GenericFunction>( saga: T, ...args: Parameters<T>): IFetchSaga<T> {
return {saga, args};
}
如果需要,您可以将参数作为数组传递。
这允许 typescript 轻松推断函数的正确参数并确保它们匹配。
function* load() {
// error: Argument of type 'string' is not assignable to parameter of type 'number'
yield call(triggerChange, fetchable(fetchData, "10", "2021-03-22"), true);
// okay :)
yield call(triggerChange, fetchable(fetchData, 10, "2021-03-22"), true);
}
问题
原始版本失败的原因与 triggerChange
是一个通用函数,可以用任何 T
调用。当我们为 triggerChange
创建 call
效果时,它不需要任何特定的 T
类型,因为 T
是在调用函数时确定的。参数的类型回落到 GenericFunction
,其中 args
是 any[]
,因此将数组分配给它没有问题。
我们的解决方案有效,因为我们通过直接调用 fetchable
来推断特定的 T
。给我们错误的是 fetchable
函数,而不是 call
。如果我们要声明 fetchable
T
只是 GenericFunction
那么我们将遇到与以前相同的问题。
// no errors, even though we want them
yield call(triggerChange, fetchable<GenericFunction>(fetchData, "10", "2021-03-22"), true);