StyledComponents with Typescript and ThemeProvider. What are the right types?
Asked Answered
S

4

16

I have problems to get the right types when using StyledComponents with ThemeProvider.

I have tried it with this approach: https://github.com/styled-components/styled-components/issues/1589

My code so far:

App.tsx

import * as React from "react";
import "./styles.css";
import theme from "./theme";
import { ThemeProvider } from "styled-components";
import StyledButton from "./StyledButton";

export default function App() {
  return (
    <ThemeProvider theme={theme}>
      <div className="App">
        <StyledButton variant="primary">MyButton</StyledButton>
      </div>
    </ThemeProvider>
  );
}

theme.ts

import "styled-components";
const theme = {
  borderRadius: "0.7rem",
  color: "yellow"
};

export default theme;

StyledButton.tsx

import styled from "styled-components";

interface IButtonProps {
  color: string;
  backgroundColor: string;
  borderRadius?: string;
}

const buttonProps = (props: any): IButtonProps => {
  /* defaultValues / primary */
  let bp: IButtonProps = {
    color: props.theme.color,
    backgroundColor: "#2862c3c4"
  };

  if (props.variant === "primary") {
    return bp;
  } else if (props.variant === "secondary") {
    bp.color = "white";
    bp.backgroundColor = "#808080c2";
  }

  return bp;
};

const StyledButton = styled.button<IButtonProps>`
  color: ${props => (props.color ? props.color : buttonProps(props).color)};
  background-color: ${props =>
    props.backgroundColor
      ? props.backgroundColor
      : buttonProps(props).backgroundColor};
  border-radius: ${props => props.theme.borderRadius};
`;

export default StyledButton;

styled-components.d.ts

import theme from "./globals/theme";

type CustomTheme = typeof theme;

declare module "styled-components" {
  export interface DefaultTheme extends CustomTheme {}
}

So what do I have to change to get rid of the any type in:

const buttonProps = (props: any): IButtonProps

and the ts warning for variant in:

<StyledButton variant="primary">MyButton</StyledButton>

Example is here:
https://codesandbox.io/embed/styledcomponents-typescript-zut79?fontsize=14&hidenavigation=1&theme=dark

Sombrero answered 22/7, 2020 at 8:7 Comment(0)
C
20

It's described in the official documentation.

In a .d.ts file add this:

import 'styled-components';

declare module 'styled-components' {
  export interface DefaultTheme {
     borderRadius: string;
     color: string;
  }
}

Courtyard answered 30/3, 2021 at 18:33 Comment(0)
K
18

Inside your src folder, create a new folder named @types and put your file styled.d.ts inside this folder. The content is the same as below.

import 'styled-components';
import theme from "your_theme_path";

type CustomTheme = typeof theme;

declare module "styled-components" {
  export interface DefaultTheme extends CustomTheme {}
}

It has worked for me.

Koonce answered 30/4, 2022 at 20:8 Comment(0)
B
2

Add as const to your theme object like this.

const theme = {
  borderRadius: "0.7rem",
  color: "yellow"
} as const;
Bastian answered 7/11, 2020 at 14:44 Comment(0)
S
0

For some reason, name styled.d.ts is not working for type definition. Make sure provide another name like style-component.d.ts.

Screwdriver answered 30/7, 2023 at 9:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.