diff --git a/src/index.d.ts b/src/index.d.ts index 022aded7e87e79..d18377d1078563 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -1,5 +1,7 @@ import * as React from 'react'; +export type ClassNameMap = Record; + /** * Component exposed by `material-ui` are usually wrapped * with the `withStyles` HOC and allow customization via @@ -10,14 +12,14 @@ import * as React from 'react'; * - `style` * - `innerRef` */ -export interface StyledComponentProps { +export interface StyledComponentProps { className?: string; - classes?: StyleClasses; + classes?: ClassNameMap; style?: Partial; innerRef?: React.Ref; } -export class StyledComponent extends React.Component< - P & StyledComponentProps +export class StyledComponent

extends React.Component< + P & StyledComponentProps > {} export type Contrast = 'light' | 'dark' | 'brown'; @@ -94,7 +96,7 @@ export { CircularProgress, LinearProgress } from './Progress'; export { default as Radio, RadioGroup } from './Radio'; export { default as Select } from './Select'; export { default as Snackbar, SnackbarContent } from './Snackbar'; -export { MuiThemeProvider, withStyles, withTheme, createMuiTheme } from './styles'; +export { MuiThemeProvider, withStyles, WithStyles, withTheme, createMuiTheme } from './styles'; import * as colors from './colors'; diff --git a/src/styles/index.d.ts b/src/styles/index.d.ts index 89a6b632704ceb..8d70173f92c3cc 100644 --- a/src/styles/index.d.ts +++ b/src/styles/index.d.ts @@ -3,6 +3,6 @@ export { default as createBreakpoints } from './createBreakpoints'; export { default as createMuiTheme, Theme } from './createMuiTheme'; export { default as createPalette } from './createPalette'; export { default as createTypography } from './createTypography'; -export { default as withStyles } from './withStyles'; +export { default as withStyles, WithStyles } from './withStyles'; export { StyleRules, StyleRulesCallback } from './withStyles'; export { default as withTheme } from './withTheme'; diff --git a/src/styles/withStyles.d.ts b/src/styles/withStyles.d.ts index d8f4ca5ea274d9..46fe99efd96134 100644 --- a/src/styles/withStyles.d.ts +++ b/src/styles/withStyles.d.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { StyledComponentProps } from '..'; +import { ClassNameMap, StyledComponentProps } from '..'; import { Theme } from './createMuiTheme'; /** @@ -9,33 +9,23 @@ import { Theme } from './createMuiTheme'; * - the `keys` are the class (names) that will be created * - the `values` are objects that represent CSS rules (`React.CSSProperties`). */ -export interface StyleRules { - [displayName: string]: Partial; -} +export type StyleRules = Record>; -export type StyleRulesCallback = (theme: Theme) => StyleRules; +export type StyleRulesCallback = (theme: Theme) => StyleRules; export interface WithStylesOptions { withTheme?: boolean; name?: string; } -declare function withStyles( - style: StyleRules | StyleRulesCallback, - options?: WithStylesOptions -): < - C extends React.ComponentType

, - P = {}, - ClassNames = {} ->( - component: C -) => C & React.ComponentClass

> +export type WithStyles = P & { + classes: ClassNameMap + theme?: Theme +}; -declare function withStyles

( - style: StyleRules | StyleRulesCallback, +export default function withStyles( + style: StyleRules | StyleRulesCallback, options?: WithStylesOptions -): ( - component: React.ComponentType

-) => React.ComponentClass

> - -export default withStyles; +):

( + component: React.ComponentType> +) => React.ComponentType

>; diff --git a/test/typescript/components.spec.tsx b/test/typescript/components.spec.tsx index 6c82c8eecb8d25..f3e5c22f7eca26 100644 --- a/test/typescript/components.spec.tsx +++ b/test/typescript/components.spec.tsx @@ -632,7 +632,7 @@ const StepperTest = () => }; const TableTest = () => { - const styles: StyleRulesCallback = theme => ({ + const styles: StyleRulesCallback<'paper'> = theme => ({ paper: { width: '100%', marginTop: theme.spacing.unit * 3, diff --git a/test/typescript/styles.spec.tsx b/test/typescript/styles.spec.tsx index cda6c826c94fc9..ce3ac83bd562d2 100644 --- a/test/typescript/styles.spec.tsx +++ b/test/typescript/styles.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { withStyles, - StyleRules, + WithStyles, createMuiTheme, MuiThemeProvider, Theme, @@ -25,29 +25,25 @@ interface StyledComponentProps { text: string; } -const Component: React.SFC< - StyledComponentProps & { classes: StyledComponentClassNames } -> = ({ classes, text }) => -

- {text} -
; - -const StyledComponent = withStyles< - StyledComponentProps, - StyledComponentClassNames ->(styles)(Component); +const StyledComponent = withStyles(styles)( + ({ classes, text }) => ( +
+ {text} +
+ ) +); ; // Also works with a plain object -const stylesAsPojo: StyleRules = { +const stylesAsPojo = { root: { background: 'hotpink', }, }; -const AnotherStyledComponent = withStyles<{}, StyledComponentClassNames>({ +const AnotherStyledComponent = withStyles({ root: { background: 'hotpink' }, })(({ classes }) =>
Stylish!
); @@ -107,20 +103,24 @@ const AllTheStyles: React.SFC = ({ theme, classes }) => ; const AllTheComposition = withTheme( - withStyles<{ theme: Theme }, StyledComponentClassNames>(styles)(AllTheStyles) + withStyles(styles)(AllTheStyles) ); -// As decorator -@withStyles(styles) -class DecoratedComponent extends React.Component< - StyledComponentProps & { classes: StyledComponentClassNames } -> { - render() { - const { classes, text } = this.props; - return ( -
- {text} -
- ); +// Can't use withStyles effectively as a decorator in TypeScript +// due to https://github.com/Microsoft/TypeScript/issues/4881 +// @withStyles(styles) +const DecoratedComponent = withStyles(styles)( + class extends React.Component> { + render() { + const { classes, text } = this.props; + return ( +
+ {text} +
+ ); + } } -} +); + +// no 'classes' property required at element creation time (#8267) +