diff --git a/packages/material-ui-styles/src/makeStyles/makeStyles.d.ts b/packages/material-ui-styles/src/makeStyles/makeStyles.d.ts index aa925271126e8e..aa91cc7a67c908 100644 --- a/packages/material-ui-styles/src/makeStyles/makeStyles.d.ts +++ b/packages/material-ui-styles/src/makeStyles/makeStyles.d.ts @@ -1,42 +1,22 @@ import { - ClassKeyOfStyles, ClassNameMap, PropsOfStyles, Styles, WithStylesOptions, } from '@material-ui/styles/withStyles'; -import { Omit, IsAny, Or, IsEmptyInterface } from '@material-ui/types'; +import { Omit } from '@material-ui/types'; import { DefaultTheme } from '../defaultTheme'; /** - * @internal - * - * If a style callback is given with `theme => stylesOfTheme` then typescript - * infers `Props` to `any`. - * If a static object is given with { ...members } then typescript infers `Props` - * to `{}`. - * - * So we require no props in `useStyles` if `Props` in `makeStyles(styles)` is - * inferred to either `any` or `{}` + * `makeStyles` where the passed `styles` do not depend on props */ -export type StylesRequireProps = Or< - IsAny>, - IsEmptyInterface> -> extends true - ? false - : true; - +export default function makeStyles( + style: Styles, + options?: Omit, 'withTheme'>, +): (props?: any) => ClassNameMap; /** - * @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 + * `makeStyles` where the passed `styles` do depend on props */ -export type StylesHook> = StylesRequireProps extends false - ? (props?: any) => ClassNameMap> - : (props: PropsOfStyles) => ClassNameMap>; - export default function makeStyles< Theme = DefaultTheme, Props extends {} = {}, @@ -44,4 +24,4 @@ export default function makeStyles< >( styles: Styles, options?: Omit, 'withTheme'>, -): StylesHook>; +): (props: Props) => ClassNameMap; diff --git a/packages/material-ui-styles/test/index.spec.tsx b/packages/material-ui-styles/src/makeStyles/makeStyles.spec.tsx similarity index 71% rename from packages/material-ui-styles/test/index.spec.tsx rename to packages/material-ui-styles/src/makeStyles/makeStyles.spec.tsx index 418a29500969ce..9d3fe1cc7d77a4 100644 --- a/packages/material-ui-styles/test/index.spec.tsx +++ b/packages/material-ui-styles/src/makeStyles/makeStyles.spec.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { Theme } from '@material-ui/core'; import { AppBarProps } from '@material-ui/core/AppBar'; import { createStyles, makeStyles } from '@material-ui/styles'; -import styled, { StyledProps } from '@material-ui/styles/styled'; // makeStyles { @@ -136,50 +135,3 @@ import styled, { StyledProps } from '@material-ui/styles/styled'; classes.other; } } - -// styled -{ - const StyledButton = styled('button')({ - background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)', - borderRadius: 3, - border: 0, - color: 'white', - height: 48, - padding: '0 30px', - boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)', - }); - const renderedStyledButton = ; - // $ExpectError - const nonExistingClassKey = ; - - interface MyTheme { - fontFamily: string; - } - const MyThemeInstance: MyTheme = { - fontFamily: 'monospace', - }; - // tslint:disable-next-line: no-empty-interface - interface MyComponentProps extends StyledProps { - defaulted: string; - } - class MyComponent extends React.Component { - static defaultProps = { - defaulted: 'Hello, World!', - }; - render() { - const { className, defaulted } = this.props; - return
Greeted?: {defaulted.startsWith('Hello')}
; - } - } - const StyledMyComponent = styled(MyComponent)( - ({ theme }: { theme: MyTheme }) => ({ - fontFamily: theme.fontFamily, - }), - ); - const renderedMyComponent = ( - - - - - ); -} diff --git a/packages/material-ui-styles/src/styled/styled.d.spec.tsx b/packages/material-ui-styles/src/styled/styled.spec.tsx similarity index 59% rename from packages/material-ui-styles/src/styled/styled.d.spec.tsx rename to packages/material-ui-styles/src/styled/styled.spec.tsx index b87332af61715b..c8df323cbc742c 100644 --- a/packages/material-ui-styles/src/styled/styled.d.spec.tsx +++ b/packages/material-ui-styles/src/styled/styled.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; -import { styled } from '@material-ui/styles'; +import { styled, StyledProps } from '@material-ui/styles'; -function styledTest() { +function themeTest() { const style = (props: { value: number }) => ({}); const styleWithTheme = (props: { value: number; @@ -46,3 +46,49 @@ function styledTest() { // error: property 'zIndex' is missing in type ... ; // $ExpectError } + +function acceptanceTest() { + const StyledButton = styled('button')({ + background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)', + borderRadius: 3, + border: 0, + color: 'white', + height: 48, + padding: '0 30px', + boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)', + }); + const renderedStyledButton = ; + // $ExpectError + const nonExistingClassKey = ; + + interface MyTheme { + fontFamily: string; + } + const MyThemeInstance: MyTheme = { + fontFamily: 'monospace', + }; + // tslint:disable-next-line: no-empty-interface + interface MyComponentProps extends StyledProps { + defaulted: string; + } + class MyComponent extends React.Component { + static defaultProps = { + defaulted: 'Hello, World!', + }; + render() { + const { className, defaulted } = this.props; + return
Greeted?: {defaulted.startsWith('Hello')}
; + } + } + const StyledMyComponent = styled(MyComponent)( + ({ theme }: { theme: MyTheme }) => ({ + fontFamily: theme.fontFamily, + }), + ); + const renderedMyComponent = ( + + + + + ); +} diff --git a/packages/material-ui-styles/test/IsEmptyInterface.spec.ts b/packages/material-ui-styles/test/IsEmptyInterface.spec.ts deleted file mode 100644 index 11452837a646e1..00000000000000 --- a/packages/material-ui-styles/test/IsEmptyInterface.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * unit testing for IsEmptyInterface utility type - */ -import { IsEmptyInterface } from '@material-ui/types'; - -// $ExpectType true -type EmptyInterfaceIsValid = IsEmptyInterface<{}>; - -// $ExpectType false -type ObjectIsValid = IsEmptyInterface; - -// $ExpectType false -type NullishIsValid = IsEmptyInterface; - -// $ExpectType false -type StringIsValid = IsEmptyInterface; - -// $ExpectType false -type NumberIsValid = IsEmptyInterface; - -// $ExpectType false -type SymbolIsValid = IsEmptyInterface; - -// $ExpectType false -type NeverIsValid = IsEmptyInterface; - -// $ExpectType false -type UnknownIsValid = IsEmptyInterface; - -// $ExpectType false -type OptionalIsValid = IsEmptyInterface<{x?: number}>; - -const noop = () => {}; -// $ExpectType false -type FunctionIsValid = IsEmptyInterface; - -// $ExpectType false -type RecordIsValid = IsEmptyInterface>; - -const someObject = { foo: 5 }; -// $ExpectType false -type ObjectWithPropertiesIsValid = IsEmptyInterface; diff --git a/packages/material-ui-types/index.d.ts b/packages/material-ui-types/index.d.ts index 4dea0a07d4d61f..c126d62247a54d 100644 --- a/packages/material-ui-types/index.d.ts +++ b/packages/material-ui-types/index.d.ts @@ -44,41 +44,3 @@ export type Omit = T extends any ? Pick = Omit & U; - -/** - * Returns true if T is any, otherwise false - */ -// https://stackoverflow.com/a/49928360/3406963 without generic branch types -export type IsAny = 0 extends (1 & T) ? true : false; - -export type Or = A extends true - ? true - : B extends true - ? true - : C extends true - ? true - : false; - -export type And = A extends true - ? B extends true - ? C extends true - ? true - : false - : false - : false; - -/** - * @internal - * - * check if a type is `{}` - * - * 1. false if the given type has any members - * 2. false if the type is `object` which is the only other type with no members - * {} is a top type so e.g. `string extends {}` but not `string extends object` - * 3. false if the given type is `unknown` - */ -export type IsEmptyInterface = And< - keyof T extends never ? true : false, - string extends T ? true : false, - unknown extends T ? false : true ->; diff --git a/packages/material-ui/src/styles/index.d.ts b/packages/material-ui/src/styles/index.d.ts index 5e980356a73cb4..74d23342c2d23d 100644 --- a/packages/material-ui/src/styles/index.d.ts +++ b/packages/material-ui/src/styles/index.d.ts @@ -7,7 +7,7 @@ export { } from './createPalette'; export { default as createStyles } from './createStyles'; export { TypographyStyle } from './createTypography'; -export { default as makeStyles, StylesHook } from './makeStyles'; +export { default as makeStyles } from './makeStyles'; export { default as responsiveFontSizes } from './responsiveFontSizes'; export { ComponentsPropsList } from './props'; export * from './transitions'; diff --git a/packages/material-ui/src/styles/makeStyles.d.ts b/packages/material-ui/src/styles/makeStyles.d.ts index 610eb0a7cf3c7c..d7702ab3c204bd 100644 --- a/packages/material-ui/src/styles/makeStyles.d.ts +++ b/packages/material-ui/src/styles/makeStyles.d.ts @@ -1,8 +1,18 @@ import { Theme as DefaultTheme } from './createMuiTheme'; -import { Styles, WithStylesOptions } from '@material-ui/styles/withStyles'; -import { StylesHook } from '@material-ui/styles/makeStyles'; +import { ClassNameMap, Styles, WithStylesOptions } from '@material-ui/styles/withStyles'; + import { Omit } from '@material-ui/types'; +/** + * `makeStyles` where the passed `styles` do not depend on props + */ +export default function makeStyles( + style: Styles, + options?: Omit, 'withTheme'>, +): (props?: any) => ClassNameMap; +/** + * `makeStyles` where the passed `styles` do depend on props + */ export default function makeStyles< Theme = DefaultTheme, Props extends {} = {}, @@ -10,6 +20,4 @@ export default function makeStyles< >( styles: Styles, options?: Omit, 'withTheme'>, -): StylesHook>; - -export { StylesHook }; +): (props: Props) => ClassNameMap;