这是因为 TS 可以从返回值推断出泛型,如下所示,
export function thunk<
Model extends object = {},
Payload = undefined,
Injections = any,
StoreModel extends object = {},
Result = any
>(
thunk: (
actions: Actions<Model>, //Applies generic to here
payload: Payload,
helpers: Helpers<Model, StoreModel, Injections>, //and here
) => Result,
): Thunk<Model, Payload, Injections, StoreModel, Result>; //Infers the generic from the return value
但是当你封装它时就不能这样做(因为正如 jcalz 指出的那样,TS 不是名义上基于的)。
export function thunk<...>(
thunk: (
actions: Actions<Model>, //How do I infer this?
payload: Payload,
helpers: Helpers<Model, StoreModel, Injections>, //Kaboom!
) => Result,
): ThunkAlias<...>; //Uh oh, there is no Model value!
您必须创建一个包装函数作为解决方法。不幸的是,自从easy-peasy
不导出所有实用程序类型来创建 thunk 这是不可能的
具体来说,这一行:helpers: Helpers<Model, StoreModel, Injections> https://github.com/ctrlplusb/easy-peasy/blob/3f632a06e0e8395185980ba8c7b047ed78b2ac13/index.d.ts#L564这就是尝试做到这一点时最令人头痛的原因。因为他们不出口Helpers https://github.com/ctrlplusb/easy-peasy/blob/3f632a06e0e8395185980ba8c7b047ed78b2ac13/index.d.ts#L148 type.
TS 4.7 发布了一项功能,允许您从类型化函数派生类型参数。https://github.com/microsoft/TypeScript/pull/47607 https://github.com/microsoft/TypeScript/pull/47607。我们可以使用这个模式来获取参数thunk
。因此,一旦发布,或者如果您同意将 TS 的开发版本作为依赖项运行,我们就可以执行此操作。安装使用npm/yarn install/add typescript@next
type ThunkAlias<TPayload = never, TReturn = any> = Thunk<
StoreModel,
TPayload,
Deps,
never,
TReturn
>
export function thunkAlias<
Model extends object = StoreModel,
Payload = undefined,
Injections = Deps,
SModel extends object = {},
Result = any
>(
args: Parameters<typeof thunk<Model, Payload, Injections, SModel, Result>>[0],
): ThunkAlias<Payload, Result> {
return thunk<Model, Payload, Injections, SModel, Result>(args)
}
您可以在此处查看模拟的演示版本:TS游乐场 https://tsplay.dev/m3yabw
解决方法是简单地复制Helpers
类型,并基于此重新定义您的包装函数。 (并导入它需要的任何其他类型)
// Yoinked from easy-peasy
type Helpers<Model extends object, StoreModel extends object, Injections> = {
dispatch: Dispatch<StoreModel>;
fail: AnyFunction;
getState: () => State<Model>;
getStoreActions: () => Actions<StoreModel>;
getStoreState: () => State<StoreModel>;
injections: Injections;
meta: Meta;
};
export function thunkAlias<
Model extends object = StoreModel,
Payload = undefined,
Injections = Deps,
SModel extends object = {},
Result = any
>(
_thunk: (
actions: Actions<Model>,
payload: Payload,
helpers: Helpers<Model, SModel, Injections>,
) => Result,
): ThunkAlias<Payload, Result> {
return thunk<Model, Payload, Injections, SModel, Result>(args)
}
附:但在某些时候,你必须问自己,为了其他地方不那么冗长,所有这些工作是否真的值得?我想这取决于你问谁...