This is the line of code I'm trying to implement.
const MaybeBigHeading = styled(Heading)( ({ big:boolean = false }) => [ big && tw`text-4xl` ]);
The error I receive is:
Property 'big' does not exist on type 'ClassAttributes<HTMLHeadingElement> & HTMLAttributes<HTMLHeadingElement> & { theme?: Theme | undefined; } & { ...; }'.ts(2339)
The error kind of makes sense to me, but I'm learning ReactJS/Typescript and am trying to implement something from a Javascript tutorial; this works in Javascript, but not in Typescript.
Not sure how to get around this in Typescript.
CodePudding user response:
Found a solution shortly after posting this
By adding
declare module "react" {
interface HTMLAttributes<T> extends DOMAttributes<T> {
big?: boolean;
}
}
to the .tsx file, I was able to use "big" as an attribute for a new Component
Full App.tsx file follows
/** @jsxImportSource @emotion/react */
import tw from "twin.macro";
import { DOMAttributes } from "react";
import styled from "@emotion/styled";
const Heading= tw.h1`text-blue-500 text-2xl p-2`;
const BigHeading = tw(Heading)`text-4xl`;
declare module "react" {
interface HTMLAttributes<T> extends DOMAttributes<T> {
big?: boolean;
}
}
const MaybeBigHeading = styled(Heading)( ({ big = false }) => [ big && tw`text-4xl text-red-300` ]);
const Container = tw.div`max-w-4xl mx-auto p-5 mt-5`;
function App() {
return (
<Container >
<BigHeading>Hello World</BigHeading>
<Heading>This is an example</Heading>
<MaybeBigHeading>This might be a Big Heading</MaybeBigHeading>
<MaybeBigHeading big>This IS a Big Heading</MaybeBigHeading>
</Container>
);
}
export default App;
CodePudding user response:
The type for the styled
function is something called a generic. A generic allows you to pass in your own types via parameters. Generic parameters are put between the angled brackets (<>
). In your case, you'd use it like this:
const MaybeBigHeading = styled(Heading)<{ big?: boolean; }>(({ big = false }) => [ big && tw`text-4xl text-red-300` ]);
See documentation on using TypeScript with Emotion too. You can see how the generic type for styled
is defined here.
A note on the solution you've discovered
In the solution you've discovered, you've extended the HTMLAttributes
interface by adding your own type for big
:
declare module "react" {
interface HTMLAttributes<T> extends DOMAttributes<T> {
big?: boolean;
}
}
Yes, this works but it's essentially a brute force method for when no other options exist. It's not a good idea because it's polluting the meaning of what an HTML attribute is and will likely cause confusion to future readers of your code (potentially yourself). big
is not an HTML attribute so should not existing on the HTML attributes interface.