gpt4 book ai didi

reactjs - Typescript Redux Thunk(类型)

转载 作者:搜寻专家 更新时间:2023-10-30 20:32:27 25 4
gpt4 key购买 nike

我有一个 redux thunk Action ,它获取一些数据然后分派(dispatch)一些 Action (这里的代码中没有显示,但你可以在下面的演示链接中找到它)

export const fetchPosts = (id: string) => (dispatch: Dispatch<TActions>) => {
return fetch('http://example.com').then(
response => {
return response.json().then(json => {
return "Success message";
});
},
err => {
throw err;
}
);
};

在我的组件中,我使用 mapDispatchToPropsbindActionCreators 从我的组件中调用此函数,如下所示:

public fetchFunc() {
this.props.fetchPosts("test").then(
res => {
console.log("Res from app", res);
},
err => {
console.log("Err from app", err);
}
);
}

由于我使用的是typescript,所以我需要在Props中定义这个函数的类型

interface IProps {
name?: string;
posts: IPost[];
loading: boolean;
fetchPosts: (id: string) => Promise<string | Error>;
}

如果我像上面那样做,Typescript 会提示我应该这样做:

fetchPosts: (id: string) => (dispatch: Dispatch<TActions>) => Promise<string | Error>; 

如果我这样做,当我在我的组件中使用 then 时,Typescript 会提示说该函数不是一个 promise 。

我创建了一个演示,您可以在其中摆弄代码

按下“从远程加载”有时会失败,只是为了查看 promise :

https://codesandbox.io/s/v818xwl670

最佳答案

问题是对 bindActionCreators 的调用在 mapDispatchToProps .在运行时 bindActionCreators基本上改变了这个 (id: string) => (dispatch: Dispatch<TActions>) => Promise<string>;进入这个(id: string) => Promise<string>; , 但类型为 bindActionCreators不反射(reflect)这种转变。这可能是因为要实现这一点,您需要直到最近才可用的条件类型。

如果我们看this来自 redux repo 的示例用法,我们看到它们通过明确指定函数的类型来完成转换:

const boundAddTodoViaThunk = bindActionCreators<
ActionCreator<AddTodoThunk>,
ActionCreator<AddTodoAction>
>(addTodoViaThunk, dispatch)

我们可以在您的代码中执行相同的操作,引用现有类型,但这会损害类型安全,因为没有检查 fetchPosts在这两种类型中将被正确输入:

const mapDispatchToProps = (dispatch: Dispatch<TActions>): Partial<IProps> =>
bindActionCreators<{ fetchPosts: typeof fetchPosts }, Pick<IProps, 'fetchPosts'>>(
{
fetchPosts
},
dispatch
);

或者我们可以使用类型断言,因为上面的方法并没有真正提供任何安全性:

const mapDispatchToProps2 = (dispatch: Dispatch<TActions>) =>
bindActionCreators({
fetchPosts: fetchPosts as any as ((id: string) => Promise<string>)
}, dispatch );

要以真正类型安全的方式执行此操作,我们需要使用 typescript 2.8 和带有辅助函数的条件类型。我们可以输入 bindActionCreators它应该的方式,并自动为生成的创建者推断正确的类型:

function mybindActionCreators<M extends ActionCreatorsMapObject>(map: M, dispatch: Dispatch<TActions>) {
return bindActionCreators<M, { [P in keyof M] : RemoveDispatch<M[P]> }>(map, dispatch);
}
const mapDispatchToProps = (dispatch: Dispatch<TActions>) =>
mybindActionCreators(
{
fetchPosts
},
dispatch
);

// Helpers
type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;

type RemoveDispatch<T extends Function> =
T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G, h: infer H, i: infer I, j: infer J) => (dispatch: Dispatch<any>) => infer R ? (
IsValidArg<J> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => R :
IsValidArg<I> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => R :
IsValidArg<H> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => R :
IsValidArg<G> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => R :
IsValidArg<F> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F) => R :
IsValidArg<E> extends true ? (a: A, b: B, c: C, d: D, e: E) => R :
IsValidArg<D> extends true ? (a: A, b: B, c: C, d: D) => R :
IsValidArg<C> extends true ? (a: A, b: B, c: C) => R :
IsValidArg<B> extends true ? (a: A, b: B) => R :
IsValidArg<A> extends true ? (a: A) => R :
() => R
) : T;

关于reactjs - Typescript Redux Thunk(类型),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49424666/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com