我有一个故事的定义如下:
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
});,当我打电话给我的传奇时,我能做些什么让args打字正确吗?
Ps.:我知道我可以在调用效果之外定义我的fetchSaga参数,但是我必须总是用一个typeof调用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);
}发布于 2021-03-23 00:13:38
解决方案
解决这个问题的建议是通过帮助函数创建IFetchSaga<T>对象。
function fetchable<T extends GenericFunction>( saga: T, ...args: Parameters<T>): IFetchSaga<T> {
return {saga, args};
}如果愿意,可以将args作为数组传递。
这样,类型记录就可以很容易地为函数推断出合适的args,并确保它们匹配。
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);
}问题
原始版本失败的原因类似于我深入研究的this answer。triggerChange是一个泛型函数,可以用任何T调用。当我们为call创建triggerChange效果时,它不需要有任何特定的T类型,因为T是在调用函数时确定的。参数的类型回到了GenericFunction,其中args是any[],因此将数组分配给它没有问题。
我们的解决方案之所以有效,是因为我们通过直接调用T来推断特定的fetchable。给我们错误的是fetchable函数,而不是call。如果我们声明fetchable T只是GenericFunction,那么我们就会遇到与以前相同的问题。
// no errors, even though we want them
yield call(triggerChange, fetchable<GenericFunction>(fetchData, "10", "2021-03-22"), true);https://stackoverflow.com/questions/66743781
复制相似问题