6

I've been using this construction that Material UI requires to deal with TypeScript issues a lot and it's really bugging me that every time I want to style a component I need to remember how to combine 2 different functions into something that will yield a hook (I could solve it with a snippet but that just never feels right to me):

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    ...styles
  })
);

So I tried of course to make it more DRY by just abstracting it away into 1 function but I can't seem to understand how to make the types work for this. Here's my clumsy attempt:

const makeUseStyles = (styleFunc: (th: Theme) => CSSProperties | CreateCSSProperties<{}>) =>
  makeStyles((theme: Theme) => {
    const st = styleFunc(theme);
    return createStyles(st);
  });

This creates 2 problems: createStyles doesn't accept st as an argument:

Type 'unknown' is not assignable to type 'PropsFunc<(value: JSSFontface, index: number, array: JSSFontface[]) => unknown, CreateCSSProperties<(value: JSSFontface, index: number, array: JSSFontface[]) => unknown>>'

And the function returned by makeUseStyles is suddenly expecting a required argument props of type (value: JSSFontface, index: number, array: JSSFontface[]) => unknown.

So I assume, since my attempt failed, that this is why there are 2 separate functions needed in the first place to appease TypeScript but it bothers me a lot that a compiler would dictate the abstractions (which it feels like it does all the time the moment I try to DRY out a bit my styling code). So my question is: why?

Michał Gacka
  • 2,935
  • 2
  • 29
  • 45

1 Answers1

9

When you use or upgrade to TypeScript version > 3.4 you don’t need to call createStyle. The const assertions that became available in this version can defeat type widening. According to a code comment, the function createStyles will be removed in MaterialUI v5 (though it hasn't been removed from v5.0.0-alpha.23 yet).

I am indeed not experiencing any type widening and this is also confirmed by eps1lon in a github issue comment. The docs should definitely be updated.

wedi
  • 1,332
  • 1
  • 13
  • 28
  • 1
    I'm using TypeScript 4.1.2. It's not clear to me from your answer how that should solve the issue. – Michał Gacka Jan 20 '21 at 10:34
  • In short: there is no need to use createStyle anymore as type widening should™ not happen when you use makeStyle. Can you add an example where it does happen? – wedi Jan 21 '21 at 17:56
  • I’m really happy there is auto completion in the IDE because I tend to forget the final ‘s’ in these function names quite often. – wedi Jan 21 '21 at 18:08
  • I see. Now I understand what you were trying to say and now that I tested it, indeed it seems that `createStyles` is not necessary. Shame that the bounty expired – Michał Gacka Jan 21 '21 at 18:21