Skip to content

Commit

Permalink
[styles] Infer optional props argument for makeStyles in TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon committed Dec 5, 2018
1 parent 734018b commit 7a9a332
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
19 changes: 17 additions & 2 deletions packages/material-ui-styles/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,24 @@ declare module '@material-ui/styles/makeStyles' {
WithStylesOptions,
} from '@material-ui/styles/withStyles';

// https://stackoverflow.com/a/49928360/3406963 without generic branch types
type IsAny<T> = 0 extends (1 & T) ? true : false;

/**
* @internal
*
* `Props` are `any` either by explicit annotation or if there are no callbacks
* from which the typechecker could infer a type so it falls back to `any`.
* See the test cases for examples and implications of explicit `any` annotation
*/
export type StylesHook<S extends Styles<any, any>> = IsAny<PropsOfStyles<S>> extends true
? (props?: any) => ClassNameMap<ClassKeyOfStyles<S>>
: (props: PropsOfStyles<S>) => ClassNameMap<ClassKeyOfStyles<S>>;

export default function makeStyles<S extends Styles<any, any>>(
styles: S,
options?: WithStylesOptions<ClassKeyOfStyles<S>>,
): (props: PropsOfStyles<S>) => ClassNameMap<ClassKeyOfStyles<S>>;
): StylesHook<S>;
}

declare module '@material-ui/styles/styled' {
Expand Down Expand Up @@ -200,9 +214,10 @@ declare module '@material-ui/styles/withStyles' {
* @internal
* This is basically the API of JSS. It defines a Map<string, CSS>,
* where
*
* - the `keys` are the class (names) that will be created
* - the `values` are objects that represent CSS rules (`React.CSSProperties`).
*
* if only `CSSProperties` are matched `Props` are inferred to `any`
*/
export type StyleRules<Props extends object, ClassKey extends string = string> = Record<
ClassKey,
Expand Down
18 changes: 17 additions & 1 deletion packages/material-ui-styles/test/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,23 @@ function testGetThemeProps(theme: Theme, props: AppBarProps): void {
);
const NoPropsComponent = () => {
const classes = useWithoutProps();
const alssoClasses = useWithoutProps({});
const alsoClasses = useWithoutProps(5);
};

// unsafe any props make the param optional
const useUnsafeProps = makeStyles(
createStyles({
root: (props: any) => ({
backgroundColor: props.deep.color,
}),
}),
);

const UnsafeProps = (props: StyleProps) => {
// would be nice to have at least a compile time error because we forgot the argument
const classes = useUnsafeProps(); // runtime: Can't read property color of undefined
// but this would pass anyway
const alsoClasses = useUnsafeProps(undefined); // runtime: Can't read property color of undefined
};
}

Expand Down

0 comments on commit 7a9a332

Please sign in to comment.