【发布时间】:2018-11-25 18:26:10
【问题描述】:
我希望标题有意义。我想要做的是有一个工厂函数,它接受一个带有参数的函数,该参数将在稍后调用返回的函数时提供。本质上:
const f = <B extends keyof any>(arg: B, fn: (props: A) => void) => <A extends Record<B, any>>(obj: A): Omit<A, B> => {
fn(obj)
delete obj[arg]
return obj
}
显然A 不适用于第一个函数定义,它必须在第二个函数定义中才能正确推断(请参阅我之前的问题How to write omit function with proper types in typescript)。
我认为至少有一种方法可以将A 限制为A extends Record<B, any>,因为这是必需的,因此第一个参数实际上是稍后提供的对象的键,同时它必须是与fn 道具相同。
这个例子是人为设计的,但本质上,redux connect 风格的 HOC 应该需要类似的东西。问题是我对 redux 类型定义的了解不够,无法知道如何为我的用例获取和修改它们。
编辑: 我要创建的 HOC 示例:
export const withAction = <A extends keyof any, B extends object>(
actionName: A,
// The B here should actually be OuterProps
actionFunc: (props: B, ...args: any[]) => Promise<any>,
) => <InnerProps extends object, OuterProps extends Omit<InnerProps, A>>(
WrappedComponent: React.ComponentType<InnerProps>,
): React.ComponentType<OuterProps> => {
return (props: OuterProps) => {
// This is a react hook, but basically it just wraps the function with some
// state so the action here is an object with loading, error, response and run
// attributes. We just need to wrap it like this to be able to reuse hook
// as a HOC for class based components.
const action = useAction((...args) => {
// At this moment the props here does not match the function arguments and
// it triggers a TS error
return actionFunc(props, ...args)
})
// The action is injected here as the actionName
return <WrappedComponent {...props} {...{ [actionName]: action }} />
}
}
// Usage:
class Component extends React.Component<{ id: number, loadData: any }> {}
// Here I would like to check that 'loadData' is actually something that the
// component want to consume and that 'id' is a also a part of the props while
// 'somethingElse' should trigger an error which it does not at the moment.
const ComponentWithAction = withAction('loadData', ({ id, somethingElse }) =>
API.loadData(id),
)(Component)
// Here the ComponentWithAction should be React.ComponentType<{id: number}>
render(<ComponentWithAction id={1} />)
【问题讨论】:
-
您还可以添加一个预期的用法示例吗?如果
fn已经有类型,那么它很简单.. 但返回的函数f只能用于特定的A... -
我添加了我正在研究的完整 HOC,希望它能解决问题。
-
它可以帮助你添加你的 HOC,我会尝试看看,但不能保证我今天会得到它......也许其他人会在此之前回答:)
-
@TitianCernicova-Dragomir 别担心你已经帮了我很多忙了。
-
如果您调用
foo(x).bar(y),编译器无法使用y的类型来推断foo()所需的类型参数。如果您将中间事物分配给变量const foox = foo(x);,然后随后调用foox.bar(y)和foox.bar(z),这一点会变得特别清楚。在调用foox.bar(y)或foox.bar(z)之前设置foox的类型。如果不是,foox.bar(y)或foox.bar(z)中的哪一个决定foox的类型?两者都有?
标签: typescript