I have created a rather basic typography component for my React application and it's throwing a Typescript error which i must admit is baffling my slightly.
Typography Component Code
import clsx from 'clsx';
const variants = {
h1: 'h1',
h2: 'h2',
h3: 'h2',
h4: 'h2',
h5: 'h2',
h6: 'h2',
subheading1: 'h6',
subheading2: 'h6',
body1: 'p',
body2: 'p',
link: 'p',
};
const typographyVariants = {
h1: 'text-6xl',
h2: 'text-5xl',
h3: 'text-4xl',
h4: 'text-3xl',
h5: 'text-2xl',
h6: 'text-1xl',
subheading1: 'text-1xl font-bold',
subheading2: 'text-1xl font-semibold',
body1: 'text-base',
body2: 'text-base font-bold',
link: 'text-xs text-primaryViolet uppercase underline font-bold',
};
export type TypographyProps = {
variant?: keyof typeof variants;
className?: string;
children: React.ReactNode | string;
};
export const Typography = ({ variant = 'body1', className, children }: TypographyProps) => {
const Component = variants[variant];
const typographyStyles = typographyVariants[variant];
return (
<Component className={clsx('font-sans', typographyStyles, className)}>{children}</Component>
);
};
Typescript Error
The '<Component' bit in the return statment is highlighted with the following error
Type '{ children: ReactNode; className: string; }' is not assignable to type 'IntrinsicAttributes'. Property 'children' does not exist on type 'IntrinsicAttributes'.ts(2322)
Anyone have any ideas?
Thanks
Lee
CodePudding user response:
const variants = {
h1: 'h1',
h2: 'h2',
h3: 'h2',
h4: 'h2',
h5: 'h2',
h6: 'h2',
subheading1: 'h6',
subheading2: 'h6',
body1: 'p',
body2: 'p',
link: 'p',
};
With no explicit type on this, typescript assigns string
to all the properties, which means Component
in const Component = variants[variant];
is also of type string
. With a type that general, the only things you're allowed to pass in to <Component />
are ones that are shared by every single element. This is represented by a type called IntrinsicAttributes
, and is just the key
property. No children allowed, no className allowed.
You can fix this by being more explicit when defining variants
. The simplest approach would just be to add as const
to the end, so that typescript will be stricter in the definition that it infers:
const variants = {
h1: 'h1',
// ...
link: 'p',
} as const;
With that change, Component
now has the type "h1" | "h2" | "h6" | "p"
, and since all of those elements allow children and className, the type error will go away.