Сложный объект в Typescript надо, чтобы classname был или строкой, или объектом
Я хочу дать возможность передавать или строку, или объект с полями типо вот так
className={{
tag: 'tag-class',
tooltip: {
base: 'tooltip-base-class',
content: 'tooltip-content-class'
},
}}
Внутри компонента я пытаюсь принять
interface TooltipProps {
className?: string | ClassNameObject;
}
interface ClassNameTooltip {
base?: string;
content?: string;
}
interface ClassNameObject {
tag?: string;
tooltip?: ClassNameTooltip;
}
Казалось что все окей, но получаю ошибку
Тип "{ tag: string; tooltip: { base: string; content: string; }; }" не может быть назначен для типа "string | (ClassNameObject & string)".
Тип "{ tag: string; tooltip: { base: string; content: string; }; }" не может быть назначен для типа "ClassNameObject & string". Тип "{ tag: string; tooltip: { base: string; content: string; }; }" не может быть назначен для типа "string"
Прошу помочи в решение такой задачи
Ответы (1 шт):
Ответ оказался прост, надо было начать копать из-начала, в общем для создания объекта я использовал Proxy чтобы можно было указать какой хочешь блок примерно как в frame motion где указывается префикс и через точку нужный блок motion.div.
А чтобы получить все свойства для указанного тэга, я их собирал как бы назад, в этом и был конфликт, что она ожидала для Proxy стандартный className: string а еще сверху пытался добавить свой className
Решение
В типе для создания Proxy нужно удалить className и после чего добавить свой.
type TooltipComponent = <T extends keyof JSX.IntrinsicElements>(
props: TooltipProps & Omit<JSX.IntrinsicElements[T], 'className'>
) => ReactElement | null;
После спокойно создаем новый элемент:
interface TooltipProps {
className?: string | ClassNameObject;
}
const createTooltipComponent = (Tag: ComponentType<any> | keyof JSX.IntrinsicElements): TooltipComponent => {
return ({
className,
}: TooltipProps): JSX.Element => {
}
)
Таким образом мы получаем именно наш className, который можем описать как хотим.
Полный код:
interface ClassNameTooltip {
base?: string;
content?: string;
}
interface ClassNameObject {
tag?: string;
tooltip?: ClassNameTooltip;
}
interface TooltipProps {
className?: string | ClassNameObject;
}
type TooltipComponent = <T extends keyof JSX.IntrinsicElements>(
props: TooltipProps & Omit<JSX.IntrinsicElements[T], 'className'>
) => ReactElement | null;
const createTooltipComponent = (Tag: ComponentType<any> | keyof JSX.IntrinsicElements): TooltipComponent => {
return ({
className,
}: TooltipProps): JSX.Element => {
return (
<Tag>
/* ... */
</Tag>
);
};
};
const tooltip: { [K in keyof JSX.IntrinsicElements]: TooltipComponent } = new Proxy({}, {
get: (_, prop: string) => createTooltipComponent(prop as keyof JSX.IntrinsicElements),
}) as { [K in keyof JSX.IntrinsicElements]: TooltipComponent };
export default tooltip;