Dealing with TypeScript issues in Material UI has been a frequent task for me, and I find it frustrating that styling components requires combining two different functions to create a hook every time. While I could use a snippet to simplify the process, it never quite feels right to me. Here is an example of the common construction I use:
const useStyles = makeStyles((theme: Theme) =>
createStyles({
...styles
})
);
In an attempt to make this process more DRY, I tried abstracting it into one function, but encountered difficulty in making the types work correctly. Here is my attempt:
const makeUseStyles = (styleFunc: (th: Theme) => CSSProperties | CreateCSSProperties<{}>) =>
makeStyles((theme: Theme) => {
const st = styleFunc(theme);
return createStyles(st);
});
This approach raised two problems: createStyles
did not accept st
as an argument, resulting in an error message:
Type 'unknown' is not assignable to type 'PropsFunc<(value: JSSFontface, index: number, array: JSSFontface[]) => unknown, CreateCSSProperties<(value: JSSFontface, index: number, array: JSSFontface[]) => unknown>>'
Furthermore, the function returned by makeUseStyles
suddenly expected a required argument props
of type
(value: JSSFontface, index: number, array: JSSFontface[]) => unknown
.
My failed attempt made me question why there is a need for two separate functions to satisfy TypeScript requirements, and why the compiler seems to dictate the abstractions when trying to streamline styling code. So, I wonder, why is this necessary?