默认值和联合类型在React组件中是如何工作的?

huangapple go评论68阅读模式
英文:

How do default values and union types work in React components?

问题

以下是翻译好的部分:

So basically I wonder why does setting the default value to a prop break a condition for types.
所以基本上我想知道为什么将默认值设置为属性会破坏类型的条件。

And the second question is why does passing children as a prop work with types fine but when calling children function in JSX it doesn't see correct types.
第二个问题是,为什么将子元素作为属性传递可以正常工作,但在JSX中调用子元素函数时类型不正确。

That's a tricky question, tried to find an answer in google, but didn't manage it 默认值和联合类型在React组件中是如何工作的?
这是一个棘手的问题,尝试在Google中找到答案,但没有成功。

英文:

I described my question with examples here:

https://codesandbox.io/s/gracious-diffie-hs57tc?file=/src/App.tsx

So basically I wonder why does setting the default value to a prop break a condition for types.
And the second question is why does passing children as a prop work with types fine but when calling children function in JSX it doesn't see correct types.

That's a tricky question, tried to find an answer in google, but didn't manage it 默认值和联合类型在React组件中是如何工作的?

答案1

得分: 0

以下是翻译好的内容:

.defaultProps

首先,我想明确一点,我发现它可能会在将来被弃用,但它仍然有效...
要定义props的默认值,可以使用defaultProps静态字段:

type Props = {
  flag: boolean;
};

const MyComp = ({ flag }: Props) => <p>{flag ? "是" : "否"}</p>;

MyComp.defaultProps = {
  flag: false
};

React.FC&lt;&gt;

我注意到,当我们在组件的第一个使用中移除flag时,会出现和第二个使用相同的问题。但我成功通过为组件添加React.FC&lt;ComponentProps&gt;类型来修复它:

const Component: React.FC&lt;ComponentProps&gt; = ({ flag, children }: ComponentProps /* 如果您愿意,可以从此处删除参数类型 */) => {
  // ...
};

现在,这段代码会报告isOpen不存在,而不是同时报告"titleisOpen都是any"的问题:

<Component children={({ title, isOpen }) => <>{isOpen ? title : "已关闭"}</>} />
//                             ^^^^^^
// 属性'isOpen'在类型'{ title: string; }'上不存在。

关于children类型推断

关于您的最后一个问题,不幸的是,我没有找到任何合乎逻辑的原因,我认为这看起来像是React TypeScript的一个bug。

我观察到,如果我们移除children的值,会得到以下错误:

<Component>{}<</Component>;
// 类型'never[]'与签名'(props: { title: string; }): ReactNode'不匹配。

因此,我们可以理解TypeScript知道正确的类型是children,并尝试进行匹配。但出于某种原因,它无法推断出我们提供的函数的类型。作为一种解决方法,您可以严格地为其添加类型,这将起作用(但我承认这不是一个好的解决方案)...

似乎它无法使用这种语法进行类型推断,我认为您应该提交一个错误报告,因为这不是正确的行为。

英文:

I played a little with your sandbox and figured out a few things.

.defaultProps

First of all I'd like to precise I just found it may be deprecated in the future, but it works...
For defining default values to props, you can use the defaultProps static field:

type Props = {
  flag: boolean;
};

const MyComp = ({ flag }: Props) =&gt; &lt;p&gt;{flag ? &quot;Yes&quot; : &quot;No&quot;}&lt;/p&gt;;

MyComp.defaultProps = {
  flag: false
};

React.FC&lt;&gt;

I noticed that when we remove the flag in the first usage of the component, the same problem as the second appears. But I managed to fix it by adding the type React.FC&lt;ComponentProps&gt; to the component:

const Component: React.FC&lt;ComponentProps&gt; = ({ flag, children }: ComponentProps /* You can remove the parameter type from here if you want*/) =&gt; {
  // ...
};

Now, this code tell that isOpen does not exist, instead of both the "title and isOpen are any" thing:

&lt;Component children={({ title, isOpen }) =&gt; &lt;&gt;{isOpen ? title : &quot;Closed&quot;}&lt;/&gt;} /&gt;
//                             ^^^^^^
// Property &#39;isOpen&#39; does not exist on type &#39;{ title: string; }&#39;.

The children type inference

About your last question, unfortunately, I didn't found any logical reason, and I think it looks like a React TypeScript bug.

I observed that if we remove the children value we get the following error:

&lt;Component&gt;{}&lt;/Component&gt;
// Type &#39;never[]&#39; provides no match for the signature &#39;(props: { title: string; }): ReactNode&#39;.

So we understand here that TypeScript is aware that the correct type is children, and tries to match it. But, for some reason, it is unable to infer the type of the parameter when we give the function. You can, as a workaround, strictly type it and it'll work (but I admit this is not a good solution)...

It seems that it cannot do the type inference with this syntax and in my opinion, you should open a bug report because this is not the correct behavior.

huangapple
  • 本文由 发表于 2023年2月23日 23:34:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75546985.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定