我做了一个简单的<If />
使用 React 的功能组件:
import React, { ReactElement } from "react";
interface Props {
condition: boolean;
comment?: any;
}
export function If(props: React.PropsWithChildren<Props>): ReactElement | null {
if (props.condition) {
return <>{props.children}</>;
}
return null;
}
它让我可以编写更清晰的代码,例如:
render() {
...
<If condition={truthy}>
presnet if truthy
</If>
...
在大多数情况下,它工作得很好,但是当我想检查例如给定变量是否未定义然后将其作为属性传递时,它就成为一个问题。我举个例子:
假设我有一个名为 <Animal />
的组件它具有以下 Props:
interface AnimalProps {
animal: Animal;
}
现在我有另一个组件可以呈现以下 DOM:
const animal: Animal | undefined = ...;
return (
<If condition={animal !== undefined} comment="if animal is defined, then present it">
<Animal animal={animal} /> // <-- Error! expected Animal, but got Animal | undefined
</If>
);
正如我所评论的,虽然事实上动物没有定义,但我无法告诉 Typescript 我已经检查过它。 animal!
的断言会起作用,但这不是我想要的。
有什么想法吗?
最佳答案
这似乎不可能。
原因:如果我们将 If
组件的内容更改为
if (props.condition) {
...
}
相反
if (!props.condition) {
...
}
您会发现,这次您希望以相反的方式处理类型差异。
<If condition={animal === undefined} comment="if animal is defined, then present it">
<Animal animal={animal} /> // <-- Error! expected Animal, but got Animal | undefined
</If>
这意味着它不是独立的,从而得出这样的结论:在这种情况下,在不触及两个组件中的任何一个的情况下不可能进行此类类型差异。
<小时/>我不确定最好的方法是什么,但这是我的想法之一。
您可以使用 typescript 的
定义Animal组件
的 Prop animal
Distributive conditional types :不可空。
文档
type T34 = NonNullable<string | number | undefined>; // string | number
使用
interface AnimalProps {
// Before
animal: Animal;
// After
animal: NonNullable<Animal>;
}
它不是由 If
组件的条件生成的,但由于您只在该条件内使用子组件
,因此设计 子组件是有意义的
的 props 为 none nullable
,条件是
type
Animal
do containundefined
.
关于javascript - 如何制作一个像 Typescript 中真正的 "If"一样工作的 React "if"组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60393467/