Home > Mobile >  Receiving an error in typescript using emotion/styled when trying to add a custom property
Receiving an error in typescript using emotion/styled when trying to add a custom property

Time:10-19

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.

  • Related