如何在 Typescript 中制作一个像真正的“if”一样的 React“If”组件?

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!会起作用,但这不是我要找的。

有任何想法吗?

kei*_*kai 4

这似乎是不可能的。

\n\n

原因:如果我们更改If组件的内容

\n\n
if (props.condition) {\n  ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

与它相反

\n\n
if (!props.condition) {\n  ...\n}\n
Run 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>\n
Run Code Online (Sandbox Code Playgroud)\n\n

这意味着它不是独立的,从而得出这样的结论:在这种情况下,在不接触两个组件中的任何一个的情况下不可能进行此类类型差异。

\n\n
\n\n

我不确定最好的方法是什么,但这是我的想法之一。

\n\n

您可以使用打字稿的 \ n分布式条件类型NonNullableAnimal component来定义props 。animal

\n\n

文档

\n\n
type T34 = NonNullable<string | number | undefined>;  // string | number\n
Run Code Online (Sandbox Code Playgroud)\n\n

用法

\n\n
interface AnimalProps {\n  // Before\n  animal: Animal;\n  // After\n  animal: NonNullable<Animal>;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

它不是由If组件的条件生成的,但由于您只使用该条件内部,因此在以下条件下将其 propschild component设计为 \xef\xbc\x8c 是有意义的child componentnone nullable

\n\n
\n

类型Animal确实包含undefined.

\n
\n