reactjs - 打字稿:排除部分中提供的属性
问题描述
我编写了一个名为的函数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
对象的键。返回的函数接受 afinalProps
类型Partial<Pick<T, K>> & Omit<T, K>
。该Omit<T, K>
部分说finalProps
必须T
具有中缺少的所有属性defaultProps
,并且该Partial<Pick<T, K>>
部分说finalProps
可能T
具有中包含的任何属性defaultProps
。并且这个函数的返回类型被断言为原始的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()
版本正常工作。
推荐阅读
- c# - 通过依赖注入获取 dbcontexts 背后的 10 多个剃须刀页面代码
- winapi - 如何优雅地终止可继承进程
- django - 与 DjangoItem 的 Scrapy 集成会产生错误
- excel - 如何在 VBA 中连接带有双引号和冒号的字符串?
- jupyter-notebook - Jupyter Lab 中有多个服务器?
- python - 从列表中抓取网站,解析全文,保存为 txt 文件 - Python
- javascript - 如何准确跟踪视频标签的当前时间?
- xamarin - Xamarin.Forms 项目中的“在当前上下文中找不到初始化组件”
- excel - 找不到变量时如何处理
- python - 如何使用 nginx 和 gunicorn 使我的 python-flask 网站 24*7 可用