返回此数组的泛型类型的类型提示数组
Posted
技术标签:
【中文标题】返回此数组的泛型类型的类型提示数组【英文标题】:Typehinting array of generic types that return this array 【发布时间】:2021-02-17 00:55:04 【问题描述】:我有一个方法useActions
,它接受一个函数数组并返回一个绑定动作数组,基本上像:
function useActions<A>(
actions: Array<ActionCreator<A> | ActionCreatorWithoutPayload>
): Array<ActionCreator<A> | ActionCreatorWithoutPayload>
const dispatch = useDispatch()
return useMemo(() =>
return actions.map((a) => bindActionCreators(a, dispatch))
, [actions, dispatch])
用法是这样的:
const [doFoo, doBar] = useActions([actions.doFoo, actions.doBar])
现在的问题是,doFoo 和 doBar 需要完全相同类型的参数。我设法通过编写额外的重载类型提示来解决这个问题:
function useActions<A extends ActionCreator<any>>(actions: [A]): [A]
function useActions<A extends ActionCreator<any>, B extends ActionCreator<any>>(actions: [A, B]): [A, B]
function useActions<A extends ActionCreator<any>, B extends ActionCreator<any>, C extends ActionCreator<any>>(
actions: [A, B, C]
): [A, B, C]
但这感觉很麻烦。是否有能够支持 n 个参数的通用方法?
【问题讨论】:
如果你改用命名属性会更容易,即。const doFoo, doBar = useActions(actions)
。那是破坏交易吗?我认为可以通过元组映射来完成,但我更擅长对象映射!
【参考方案1】:
使用数组
绑定一个动作创建者根本不会改变它的签名。它仍然需要一个有效负载并返回一个动作。这让生活变得轻松,因为我们不需要映射任何类型。我们只需要返回提供的相同元组。我们没有让useActions
上的泛型引用特定的动作类型,而是让它引用整个元组。然后我们只返回相同的类型。
function useActions<A extends Array<ActionCreator<any> | ActionCreatorWithoutPayload>>(
actions: A
): A
但是现在由于actions.map
,我们在钩子的主体内部有一个错误,因为array.map
的类型不考虑我们的数组元素是不同类型的,并且会将它们组合在一起。我们通过在 useMemo
调用之后添加 as A
来抑制这种情况,以将类型细化回我们知道的应该是什么。
function useActions<A extends Array<ActionCreator<any> | ActionCreatorWithoutPayload>>(
actions: A
): A
const dispatch = useDispatch()
return useMemo(() =>
return actions.map((a) => bindActionCreators(a, dispatch))
, [actions, dispatch]) as A;
Playground Link
使用对象
bindActionCreators
函数可以接受动作创建者的键控对象,无论如何,这就是您开始使用的对象。那么为什么不将它们全部绑定并获取我们需要的那些呢?
我们不再需要使用这种方法的任何as
断言,因为bindActionCreators
会自行返回正确的类型。我们从redux
导入类型ActionCreatorsMapObject
作为我们的通用A
将扩展的基础。
function useActions<A extends ActionCreatorsMapObject<any>>(
actions: A
): A
const dispatch = useDispatch();
return useMemo(() =>
return bindActionCreators(actions, dispatch);
, [actions, dispatch]);
你现在的用法变成了:
const doFoo, doBar = useActions(actions);
Playground Link
【讨论】:
以上是关于返回此数组的泛型类型的类型提示数组的主要内容,如果未能解决你的问题,请参考以下文章