首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型记录反映“`isValidElement`”类型保护没有按预期工作

类型记录反映“`isValidElement`”类型保护没有按预期工作
EN

Stack Overflow用户
提问于 2022-12-02 12:25:42
回答 1查看 34关注 0票数 0

我有一个像这样实现的工具提示组件(我已经简化了它),它可以通过将一个值传递给tooltip ReactElement以两种不同的方式使用,或者它将是一个JSX元素,或者是一个回调函数,最终返回一个ReactElement

代码语言:javascript
复制
import { isValidElement, ReactNode, useCallback, useState } from 'react';
import { Portal } from 'react-portal';

interface ChildrenProps {
    onHide: () => void;
    onShow: () => void;
}

type TooltipCallback = (onHide: () => void) => ReactNode;

export interface Props {
    tooltip: ReactNode | TooltipCallback;
    children: (props: ChildrenProps) => ReactNode;
}

export function Tooltip({ children, tooltip }: Props) {
    const [show, setShow] = useState(false);

    const onHide = useCallback(() => {
        setShow(false);
    }, []);

    const onShow = useCallback(() => {
        setShow(true);
    }, []);

    return (
        <>
            {children({ onHide, onShow })}
            <Portal>
                {show && tooltip !== null && tooltip !== undefined && (
                    <div className="tooltip">
                        {/* TS complains here */}
                        {isValidElement(tooltip) ? tooltip : tooltip(onHide)}
                    </div>
                )}
            </Portal>
        </>
    );
}

通过将回调函数传递给tooltip来使用

代码语言:javascript
复制
<Tooltip
    tooltip={(onHide) => (
        <div>
            <span>
                In this tooltip, the only way to close it is by clicking the close button in the tooltip
            </span>
            <button onClick={onHide}>close</button>
        </div>
    )}
>
    {({ onShow }) => <span onMouseOver={onShow}>Some text that triggers tooltip</span>}
</Tooltip>

通过将ReactElement传递给tooltip来使用

代码语言:javascript
复制
<Tooltip
    tooltip={
        <span>This is a tooltip that will be closed when goes away when your mouse leaves</span>
    }
>
    {({ onShow, onHide }) => (
        <span onMouseLeave={onHide} onMouseOver={onShow}>
            Some text that triggers tooltip
        </span>
    )}
</Tooltip>;

但打字本却在抱怨:

代码语言:javascript
复制
This expression is not callable.
  Not all constituents of type 'string | number | boolean | {} | ReactNodeArray | TooltipCallback' are callable.
    Type 'string' has no call signatures.ts(2349)

但是,由于我有isValidElement(tooltip)检查,所以在尝试在else子句中使用回调函数呈现工具提示时,可以保证工具提示的类型不是string _ number \ {} _{}_ ReactNodeArray

如何修复此TS错误?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-12-02 12:30:10

代码的问题是工具提示支柱被声明为ReactNode | TooltipCallback类型,因此TypeScript不知道它将始终是条件的TooltipCallback子句中的TooltipCallback。

要解决这个问题,您可以在else子句中的tooltip变量中添加一个断言,以告诉TypeScript在这一点上它肯定是一个TooltipCallback。您可以通过在工具提示变量之后添加为TooltipCallback来实现这一点,如下所示:

代码语言:javascript
复制
{isValidElement(tooltip) ? tooltip : (tooltip as TooltipCallback)(onHide)}

有了这一更改,TypeScript将不再抱怨else子句中对tooltip()的调用。

下面是应用更改的完整代码:

代码语言:javascript
复制
import { isValidElement, ReactNode, useCallback, useState } from 'react';
import { Portal } from 'react-portal';

interface ChildrenProps {
    onHide: () => void;
    onShow: () => void;
}

type TooltipCallback = (onHide: () => void) => ReactNode;

export interface Props {
    tooltip: ReactNode | TooltipCallback;
    children: (props: ChildrenProps) => ReactNode;
}

export function Tooltip({ children, tooltip }: Props) {
    const [show, setShow] = useState(false);

    const onHide = useCallback(() => {
        setShow(false);
    }, []);

    const onShow = useCallback(() => {
        setShow(true);
    }, []);

    return (
        <>
            {children({ onHide, onShow })}
            <Portal>
                {show && tooltip !== null && tooltip !== undefined && (
                    <div className="tooltip">
                        {/* TS no longer complains here */}
                        {isValidElement(tooltip) ? tooltip : (tooltip as TooltipCallback)(onHide)}
                    </div>
                )}
            </Portal>
        </>
    );
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74655747

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档