Я занимаюсь разработкой библиотеки компонентов с помощью React и TypeScript.
В настоящее время я создаю компонент Tooltip.
В файле types.ts я определяю типы этого компонента. Код:
import { DetailedHTMLProps, HTMLAttributes, ReactNode } from 'react';
export type TooltipPosition = 'top' | 'right' | 'bottom' | 'left';
export type TooltipTrigger = 'hover' | 'click';
type HTMLDivProps = DetailedHTMLProps<
HTMLAttributes<HTMLDivElement>,
HTMLDivElement
>;
export interface TooltipProps extends Omit<HTMLDivProps, 'title'> {
/**
* Tooltip title
*/
title: ReactNode;
/**
* If true, Tooltip will be visible
*/
isVisible?: boolean;
/**
* Tooltip position
*/
position?: TooltipPosition;
/**
* Event must be triggered to display Tooltip
*/
trigger?: TooltipTrigger;
/**
* if true, this will keep the tooltip active even if the mouse is outside the trigger element
*/
interactive?: boolean;
/**
* The number of milliseconds to wait before showing the tooltip.
*/
enterDelay?: number;
/**
* The number of milliseconds to wait before hiding the tooltip.
*/
hideDelay?: number;
/**
* Tooltip children
*/
children?: ReactNode;
}
Проблема в том, что кажется, что Omit не работает. Даже пытаясь опустить «заголовок», TypeScript по-прежнему утверждает, что указанный мной тип не применим к определенному стилю в TypeScript.
Ошибка:
Error:(52, 51) TS2769: No overload matches this call.
Overload 1 of 2, '(props: Pick<Pick<Pick<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "title" | "key" | ... 252 more ... | "onTransitionEndCapture"> & { ...; } & TooltipProps, "ref" | ... 260 more ... | "hideDelay"> & Partial<...>, "ref" | ... 260 more ... | "hideDelay"> & { ...; } & { ...; }): ReactElement<...>', gave the following error.
Type 'ReactNode' is not assignable to type 'string | (string & {}) | (string & ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)>) | (string & ReactNodeArray) | (string & ReactPortal) | undefined'.
Type 'null' is not assignable to type 'string | (string & {}) | (string & ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)>) | (string & ReactNodeArray) | (string & ReactPortal) | undefined'.
Overload 2 of 2, '(props: StyledComponentPropsWithAs<"div", DefaultTheme, TooltipProps, never>): ReactElement<StyledComponentPropsWithAs<"div", DefaultTheme, TooltipProps, never>, string | ... 1 more ... | (new (props: any) => Component<...>)>', gave the following error.
Type 'ReactNode' is not assignable to type 'string | (string & {}) | (string & ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)>) | (string & ReactNodeArray) | (string & ReactPortal) | undefined'.
Type 'null' is not assignable to type 'string | (string & {}) | (string & ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)>) | (string & ReactNodeArray) | (string & ReactPortal) | undefined'.
Мой компонент:
import React, { useState, useEffect, useRef } from 'react';
import { TooltipProps } from './types';
import { INITIAL_IS_VISIBLE } from './config';
import { TooltipContainer, TooltipStyled } from './styles';
const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>((props, ref) => {
const {
children,
enterDelay,
hideDelay,
interactive,
position,
title,
trigger,
isVisible,
} = props;
const [isTooltipVisible, setIsTooltipVisible] = useState<boolean>(
INITIAL_IS_VISIBLE
);
// Settings refs
const wrapper =
(ref as React.RefObject<HTMLDivElement>) ||
React.useRef<HTMLDivElement>(null);
const handleVisibility = (e: MouseEvent | React.SyntheticEvent) => {
if (wrapper?.current && !wrapper?.current.contains(e.target as Node)) {
return setIsTooltipVisible(false);
}
return setIsTooltipVisible(prevVisibility => !prevVisibility);
};
// eslint-disable-next-line consistent-return
useEffect(() => {
if (trigger === 'click') {
document.addEventListener('click', handleVisibility);
return () => {
document.removeEventListener('click', handleVisibility);
};
}
}, []);
return (
<TooltipContainer
ref={wrapper}
onMouseOver={() => trigger === 'hover' && setIsTooltipVisible(true)}
onFocus={() => trigger === 'hover' && setIsTooltipVisible(true)}
onMouseLeave={() => trigger === 'hover' && setIsTooltipVisible(false)}
>
{children}
<TooltipStyled isVisible={isTooltipVisible} title={title}>
{title}
</TooltipStyled>
</TooltipContainer>
);
});
Tooltip.defaultProps = {
position: 'top',
trigger: 'hover',
};
export default Tooltip;