I use this structure to be able to use the Avatar as any ElementType
interface AvatarOwnProps {
className?: string
src?: string
alt?: string
color?: AvatarColor
theme?: AvatarTheme
size?: AvatarSize
}
type AvatarProps<T extends ElementType = 'div'> = {
as?: T
} & ComponentPropsWithoutRef<T> & AvatarOwnProps
export const Avatar = memo(<T extends ElementType = 'div'>(props: AvatarProps<T>) => {
...
return (
<Component className={classNames(cls.Avatar, {}, additional)} {...other}>
<img src={initialSrc} alt={alt} />
</Component>
)
}
And when I try to use autocomplete, only my types (AvatarOwnProps) are displayed, but if I manually write for example onClick, TypeScript doesn't complain and everything works as it should. It's not critical as I can still put in the attribute I want on my own, but could this be a problem in my code? I am using WebStorm to write the code
The problem was quite obvious, when I re-built a similar structure for another component I noticed that the autocomplete was working. Unlike the Avatar component, memo() was not used in it. Having removed it from the code, everything really worked as it should.
Here's what it might look like:
interface AvatarProps<T extends ElementType = 'div'> {
className?: string
src?: string
as?: T
alt?: string
color?: AvatarColor
theme?: AvatarTheme
size?: AvatarSize
}
type Props<T extends ElementType> = AvatarProps<T> & Omit<ComponentPropsWithoutRef<T>, keyof AvatarProps<T>>
export const Avatar = <T extends ElementType = 'div'>(props: Props<T>) => {
const {
as: Component = 'div',
...
} = props
return (
<Component>
...
</Component>
)
}