我编写了一个名为 withDefaults
的函数它接受一个 React 组件(实际上是一个函数)并提供一个具有默认参数值的对象。它返回一个函数,该函数调用原始 React 组件(函数)并将默认参数与最终参数集合并。
当默认集中提供了所需参数时,如何使这些参数不再需要?
function withDefaultProps<C extends React.ElementType>(Component: c) {
const ResultComponent = Component as React.FunctionComponent;
return (
(defaultProps: Partial<React.ComponentProps<C>>) => (
(finalProps: React.ComponentProps<C>) => (
<ResultComponent {...defaultProps} {...finalProps}>
{finalProps.children}
</ResultComponent>
)
)
)
}
例如,我有一个组件需要 a
和b
作为属性。
type MyCompProps = {
a: string,
b: string
};
function MyComp(props: MyCompProps) {
return null; // My react structure here
}
const MyPrefilledComp = withDefaultProps(MyComp)({ a: 'alwaysThisString' });
这里是 Typescript 错误出现的地方。当我尝试使用MyPrefilledComp
时它仍然要求我提供 a
属性,即使它有默认值。我该如何调整我的withDefaulProps
方法使其可选,而不使所有属性可选。我已经尝试过使用 keyOf 进行 Diff 和 Omit,但我的 Typescript 非常初级,所以我可能做错了。
// Typescript error: Property a is required
function MyApp() {
return (
<MyPrefilledComp b="a non default value" />
)
}
我尝试简化它,并且可以轻松地看出问题出在哪里,我只是不确定如何解决它。类似:Omit<OriginalProps, Partial<OriginalProps>>
但该部分根据调用被赋予动态类型。
function withDefaults(defaultProps: Partial<OriginalProps>) {
return function wrapper(finalProps: OriginalProps) {
return {
...defaultProps,
...finalProps
};
}
}
最佳答案
我倾向于写你的 withDefaults()
最后的函数是这样的:
const makeWithDefaults = <T,>() =>
<K extends keyof T>(defaultProps: Pick<T, K>) =>
(finalProps: Partial<Pick<T, K>> & Omit<T, K>) =>
({ ...defaultProps, ...finalProps }) as T;
type MyCompProps = {
a: string,
b: string
};
const withDefaults = makeWithDefaults<MyCompProps>();
请注意makeWithDefaults()
除了返回一个函数之外,在运行时没有做太多事情,但在编译时你可以使用泛型参数 T
指定您要构建的实际对象类型。
它返回的函数使用实用程序类型 Pick<T, K>
, Partial<T>
,和 Omit<T, K>
.
一次T
指定后,withDefaults()
函数将接受 defaultProps
具有来自 T
的任何属性子集的对象,并会推断 K
成为这个defaultProps
的 key 目的。返回的函数接受 finalProps
类型 Partial<Pick<T, K>> & Omit<T, K>
。 Omit<T, K>
部分说 finalProps
必须具有 T
中的所有属性defaultProps
中缺少哪些内容,以及Partial<Pick<T, K>>
部分说 finalProps
可能具有 T
中的任何属性包含在 defaultProps
中。该函数的返回类型为 asserted为原创T
(这应该是真的,但编译器无法验证它)。
让我们看看它是否有效:
const hasDefaultA = withDefaults({ a: "hello" });
const foo = hasDefaultA({ b: "works" });
console.log(JSON.stringify(foo)); // {"a":"hello","b":"works"}
const bar = hasDefaultA({}); // error! property b missing
const baz = hasDefaultA({ a: "goodbye", b: "works" });
console.log(JSON.stringify(baz)); // { "a": "goodbye", "b": "works" }
看起来不错。我没有具体的reactjs经验,所以我会听从其他人关于如何制作你的withDefaultProps()
的信息。版本工作。
关于reactjs - Typescript:排除部分中提供的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64920960/