2

Edit

This is what I ended up doing:

import { Theme } from '@material-ui/core/styles';
import { IPaletteOptions, PaletteOptions } from '@material-ui/core/styles/createPalette';

import { ClassNameMap, Styles, WithStylesOptions } from '@material-ui/styles/withStyles';
import { Omit } from '@material-ui/types';

type TBackground = {
    nav: string;
    topBar: string;
};

declare module '@material-ui/core/styles/createPalette' {
    export interface IPaletteOptions extends PaletteOptions {
        background: TBackground;
        type: 'dark' | 'light';
    }
}

declare module '@material-ui/core/styles' {
    export type ITheme = Theme & { palette: IPaletteOptions };

    export function createMuiTheme(options?: ThemeOptions, ...args: Record<string, unknown>[]): ITheme;

    export function useTheme<T = ITheme>(): T;

    export function makeStyles<Theme = ITheme, Props extends object = {}, ClassKey extends string = string>(
        styles: Styles<ITheme, Props, ClassKey>,
        options?: Omit<WithStylesOptions<ITheme>, 'withTheme'>,
    ): keyof Props extends never
        ? // `makeStyles` where the passed `styles` do not depend on props
          (props?: any) => ClassNameMap<ClassKey>
        : // `makeStyles` where the passed `styles` do depend on props
          (props: Props) => ClassNameMap<ClassKey>;
}

Now, ITheme is implicitly assumed whenever I need it to be.


I'm trying to ensure that whenever I create a theme with createMuiTheme and that whenever I use the makeStyles or the useTheme hooks, that the resulting theme object is always of type ITheme.

I've created a theme.d.ts file in my project and I've redefined the core module from @material-ui as the following:

import { Theme, ThemeOptions } from "@material-ui/core/styles";
import {
  IPaletteOptions,
  PaletteOptions
} from "@material-ui/core/styles/createPalette";

import {
  ClassNameMap,
  Styles,
  WithStylesOptions
} from "@material-ui/styles/withStyles";
import { Omit } from "@material-ui/types";

declare module "@material-ui/core" {
  export type ITheme = Theme & { palette: IPaletteOptions };

  export function createMuiTheme(
    options?: ThemeOptions,
    ...args: Record<string, unknown>[]
  ): ITheme;

  export function makeStyles<
    ITheme = ITheme,
    Props extends object = {},
    ClassKey extends string = string
  >(
    styles: Styles<ITheme, Props, ClassKey>,
    options?: Omit<WithStylesOptions<ITheme>, "withTheme">
  ): keyof Props extends never // `makeStyles` where the passed `styles` do not depend on props
    ? (props?: any) => ClassNameMap<ClassKey> // `makeStyles` where the passed `styles` do depend on props
    : (props: Props) => ClassNameMap<ClassKey>;

  export function useTheme<T = ITheme>(): T;
}

I've taken the function definition straight out of @material-ui/core and all I did was change Theme to ITheme everywhere.

However, this doesn't seem to work, and any theme object is always of type Theme.

What am I doing wrong here and is there perhaps a different approach that I should be taking, other than module augmentation?

trusting-haslett-6l9zv

Mike K
  • 7,621
  • 14
  • 60
  • 120

0 Answers0