Eli*_*hen 12 javascript typescript reactjs
我<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;
}
Run Code Online (Sandbox Code Playgroud)
它让我可以编写更清晰的代码,例如:
render() {
...
<If condition={truthy}>
presnet if truthy
</If>
...
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,它工作得很好,但是当我想检查例如给定变量是否未定义然后将其作为属性传递时,它就成了一个问题。我举个例子:
假设我有一个名为的组件<Animal />,它具有以下道具:
interface AnimalProps {
animal: Animal;
}
Run Code Online (Sandbox Code Playgroud)
现在我有另一个组件可以呈现以下 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>
);
Run Code Online (Sandbox Code Playgroud)
正如我所评论的,虽然实际上没有定义动物,但我无法告诉 Typescript 我已经检查过它。断言animal!会起作用,但这不是我要找的。
有任何想法吗?
原因:如果我们更改If组件的内容
if (props.condition) {\n ...\n}\nRun Code Online (Sandbox Code Playgroud)\n\n与它相反
\n\nif (!props.condition) {\n ...\n}\nRun Code Online (Sandbox Code Playgroud)\n\n您会发现,这次您希望以相反的方式处理类型差异。
\n\n <If condition={animal === undefined} comment="if animal is defined, then present it">\n <Animal animal={animal} /> // <-- Error! expected Animal, but got Animal | undefined\n </If>\nRun Code Online (Sandbox Code Playgroud)\n\n这意味着它不是独立的,从而得出这样的结论:在这种情况下,在不接触两个组件中的任何一个的情况下不可能进行此类类型差异。
\n\n我不确定最好的方法是什么,但这是我的想法之一。
\n\n您可以使用打字稿的 \ n分布式条件类型:NonNullableAnimal component来定义props 。animal
文档
\n\ntype T34 = NonNullable<string | number | undefined>; // string | number\nRun Code Online (Sandbox Code Playgroud)\n\n用法
\n\ninterface AnimalProps {\n // Before\n animal: Animal;\n // After\n animal: NonNullable<Animal>;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n它不是由If组件的条件生成的,但由于您只使用该条件内部,因此在以下条件下将其 propschild component设计为 \xef\xbc\x8c 是有意义的child componentnone nullable
\n\n类型
\nAnimal确实包含undefined.