我有一个像这样实现的工具提示组件(我已经简化了它),它可以通过将一个值传递给tooltip ReactElement以两种不同的方式使用,或者它将是一个JSX元素,或者是一个回调函数,最终返回一个ReactElement:
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来使用
<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来使用
<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>;但打字本却在抱怨:
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错误?
发布于 2022-12-02 12:30:10
代码的问题是工具提示支柱被声明为ReactNode | TooltipCallback类型,因此TypeScript不知道它将始终是条件的TooltipCallback子句中的TooltipCallback。
要解决这个问题,您可以在else子句中的tooltip变量中添加一个断言,以告诉TypeScript在这一点上它肯定是一个TooltipCallback。您可以通过在工具提示变量之后添加为TooltipCallback来实现这一点,如下所示:
{isValidElement(tooltip) ? tooltip : (tooltip as TooltipCallback)(onHide)}有了这一更改,TypeScript将不再抱怨else子句中对tooltip()的调用。
下面是应用更改的完整代码:
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>
</>
);
}https://stackoverflow.com/questions/74655747
复制相似问题