Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript Typings with createUseStyles from react-jss

I'm having a heck of a time getting my typings correct so I was curious if anyone had a working example or some feedback as to where I am going wrong. There are two things I need to happen with this instance of createUseStyles, accept the theme as well as props.

I took the example from the documentation website, and of course right off the bat its already throwing TypeScript errors, which is understandable:

(pasting screenshot just to show typescript errors)

image

code block from screenshot:

import React, { ReactNode, CSSProperties } from "react";
import {
  createUseStyles,
  useTheme,
  ThemeProvider,
  DefaultTheme,
  Styles
} from "react-jss";

interface Props {
  children: ReactNode;
  useRed: boolean;
}

interface PUTheme {
  colorPrimary: string;
  altColor: string;
}

const useStyles = createUseStyles({
  button: {
    background: ({ theme }) => theme.colorPrimary
  },
  label: {
    fontWeight: "bold"
  }
});

const Button2: React.FC<Props> = ({ children, ...props }) => {
  const theme = useTheme();
  console.log(theme);
  const classes = useStyles({ ...props, theme });
  return (
    <button className={classes.button}>
      <span className={classes.label}>{children}</span>
    </button>
  );
};

const theme = {
  colorPrimary: "green",
  altColor: "red"
};

const App = () => (
  <ThemeProvider theme={theme}>
    <Button2 useRed={true}>I am a button 2 with green background</Button2>
  </ThemeProvider>
);

export default App;

The error found here (Error 1) is:

  button: {
    background: ({ theme }) => theme.colorPrimary
  },

Property 'colorPrimary' does not exist on type 'Theme'.ts(2339)

Makes sense to an extent - it doesn't know what our theme consists of, so moving on...

The error found here (Error 2) for theme is:

const classes = useStyles({ ...props, theme });

Type 'DefaultTheme' is not assignable to type 'Theme'. Type 'null' is not assignable to type 'Theme'.ts(2322)

Right away.. I'm a little confused. But let's type some things and see how it works out...

Adding an interface for my theme doesn't seem to change any of the above errors:

interface PUTheme {
  colorPrimary: string;
  altColor: string;
}

const theme: PUTheme = {
  colorPrimary: "green",
  altColor: "red"
};

So since adding an interface to my theme object doesn't seem to accomplish much, I was able to satisfy the error from Error 1 by adding typings. While this calms TypeScript down it feels, wrong?

const useStyles = createUseStyles({
  button: {
    background: ({ theme }: {theme: PUTheme}) => theme.colorPrimary
  },
  label: {
    fontWeight: "bold"
  }
});

However, this still leaves me with Error 2 except the error has changed slightly

Type 'DefaultTheme' is not assignable to type 'PUTheme'. Type 'null' is not assignable to type 'PUTheme'

I've tried following back the typings in react-jss but perhaps this is over my head at the moment.

Does anyone have any tips or insight into what I'm doing wrong or working examples? Also, here is a link to my code sandbox if you wish to see it in action.

like image 826
erwstout Avatar asked Jun 12 '26 18:06

erwstout


1 Answers

I think I've found the solution. The passing of theme/props to the classes still feels strange to me but it works and satisfies TypeScript.

import React, { ReactNode } from "react";
import { createUseStyles, useTheme, ThemeProvider } from "react-jss";

interface Props {
  children: ReactNode;
  useRed: boolean;
}

interface PUTheme {
  colorPrimary: string;
  altColor: string;
}

const useStyles = createUseStyles({
  button: {
    background: ({
      theme,
      useRed
    }: {
      theme: PUTheme;
      useRed: Props["useRed"];
    }) => (useRed ? theme.altColor : theme.colorPrimary)
  },
  label: {
    fontWeight: "bold"
  }
});

const Button2: React.FC<Props> = ({ children, ...props }) => {
  const theme = useTheme<PUTheme>();
  const classes = useStyles({ ...props, theme });
  return (
    <button className={classes.button}>
      <span className={classes.label}>{children}</span>
    </button>
  );
};

const theme: PUTheme = {
  colorPrimary: "green",
  altColor: "red"
};

const App = () => (
  <ThemeProvider theme={theme}>
    <Button2 useRed={true}>I am a button 2 with green background</Button2>
  </ThemeProvider>
);

export default App;

The main thing I believe was missing was having useTheme typed const theme = useTheme<PUTheme>();

View working Code Sandbox here!

like image 157
erwstout Avatar answered Jun 15 '26 11:06

erwstout



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!