Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript Typings - Add new props type for withStyles #7830

Closed
vyrotek opened this issue Aug 18, 2017 · 6 comments
Closed

TypeScript Typings - Add new props type for withStyles #7830

vyrotek opened this issue Aug 18, 2017 · 6 comments

Comments

@vyrotek
Copy link

vyrotek commented Aug 18, 2017

Suggestion

Currently the typings for withStyles looks like this

  const withStyles: <P = {}, ClassNames = {}>(
    style: StyleRules | StyleRulesCallback,
    options?: WithStylesOptions
  ) => (
    component: React.ComponentType<P & { classes: ClassNames }>
  ) => React.ComponentClass<P>;

May I request a type be created and exported to represent the prop values that will be added when withStyles is used? Something similar to WithWidthEnhancement would be useful. It would allow people to compose it with their own custom component prop types.

Example Usage

type MyProps = AppProps & WithWidthEnhancement & WithStylesEnhancement;
export default class App extends React.Component<MyProps, State> { ...

I think this new type not only needs classes: ClassNames but also a theme field now that you can toggle that to be included through the options.

Another thing to consider might be to name these interfaces WithWidthProps and WithStylesProps instead.

@vyrotek
Copy link
Author

vyrotek commented Aug 18, 2017

I forgot to ping @sebald in the previous post so here it is. :)

If there are other ways to get the benefits of a fully typed this.props reference then I'm open to anything. I'm relatively new to "tsx". Using type intersecting is the only way I've found to get all the available fields on props. I'm also learning that a lot of HOCs aren't really suited to be used as decorators.

Are there other approaches has anyone else has taken to get fully typed this.props?

@sebald
Copy link
Member

sebald commented Aug 21, 2017

Could you elaborate what you mean by fully typed this.props reference/get fully typed this.props?


What do you think about this? Would this be enough?

  const withStyles: <P = {}, ClassNames = {}>(
    style: StyleRules | StyleRulesCallback,
    options?: WithStylesOptions
  ) => (
    component: React.ComponentType<P & { classes: ClassNames }>
-  ) => React.ComponentClass<P>;
+  ) => React.ComponentClass<P & { classes: ClassNames, theme: Theme }>;

@vyrotek
Copy link
Author

vyrotek commented Aug 21, 2017

I need to combine all the types related to various HOCs in order to get a fully typed props instance.

In the example below I'm using @withWidth() and @withStyles() so I want to get type hints in VSCode on this.props to show this.props.width and this.props.classes, etc. I added WithWidthEnhancement to AllAppProps to give me this.props.width but I don't have a type to use to add whatever props withStyles adds since the typing didn't use an interface or class to add them. Because of this I have to "&" it like I did below with & { classes: ClassNames, theme: Theme } which I didn't like.

interface AppProps {
    someValue: number;
}

type AllAppProps = AppProps & WithWidthEnhancement & { classes: ClassNames, theme: Theme };

@withWidth()
@withStyles(styles, { withTheme: true })
export default class App extends React.Component<AllAppProps, AppState> {
    render() {
        return (
            <div>
                width: {this.props.width}                                       
            </div>
        );
    } . . .

At the very least what I was requesting was an interface called WithStylesEnhancment or something which would include the fields @withStyles adds. That way if any fields were added to removed in the future I would automatically have them available.

In order to accomplish this I would expect the change to look like:

interface WithStylesEnhancement {
    classes: ClassNames;
    theme: Theme;
}
. . . 
) => React.ComponentClass<P & WithStylesEnhancement>;

My final comment was just about a naming convention for the interfaces expose for them. I didn't know how attached you were to the term "Enhancement" versus something like "Props". Then we would have WithWidthProps and WithStylesProps types available to use.

Does that make sense?

@vyrotek
Copy link
Author

vyrotek commented Aug 21, 2017

I'm just playing with basic drawer stuff right now like this.

const styles = theme => ({
    list: {
        width: 250,
        flex: 'initial'
    },
    smallDrawerPaper: {
        marginTop: 0,
        zIndex: 5
    },
    fullDrawerPaper: {
        marginTop: 64,
        zIndex: 5
    },
    content: {
        marginTop: 64
    }
});

type AllAppProps = AppProps & WithWidthEnhancement & { classes: any };

@withWidth()
@withStyles(styles, { withTheme: true })
export default class App extends React.Component<AllAppProps, AppState> { ...

Are you using the latest type definition? You might be getting the same errors I was yesterday when I tried to use them and it broke everything for me. I can't get them to work for me at all now.

I'm also still trying to decide whether it's correct to use these HOCs as decorators or not. Using it like above is "working" for me if I don't use the type definition.

Sorry I can't be more hopeful. My plan right now is to wait and see if the typings issues from here get fixed and address my problems. Then I'll be back to investigating this type stuff again. #7853 (comment)

@sebald
Copy link
Member

sebald commented Aug 22, 2017

The only preference I have when it comes to the typings is not starting every type with an "I" 😁 If people find the word "Enhancement" weird and have problems understanding them, it should be changed. At my company, we use this term whenever something is enhanced by a HOC, this originate from recompose.

I personally was super hyped @ decorators (no pun intended). But stopped using them after leaving Angualr for React. Reasons are (a) they don't fit the functional style, we try to implement at my company, (b) make testing harder, if you declare your "bare bone" component and export it and then have an additional enchancer step, you can test both parts in isolation.

export SomeComponent:React.SFC<AllProps & WithWidthEnhancement> () => { /*  ... */ }

export enhance = compose<AllProps & WithWidthEnhancement, AllAppProps>(
  withWidth,
  withStyles(styles, { withTheme: true })
);

export default enhance(SomeComponent);

Hope this make sense.

@sebald
Copy link
Member

sebald commented Aug 22, 2017

On other note: As soon as #7853 is resolved, I'll update the typings.

sebald pushed a commit that referenced this issue Aug 24, 2017
- add `theme`
- enhanced components has "styled props"

Closes #7830
sebald added a commit that referenced this issue Aug 24, 2017
…nButton (#7897)

* [typescript] Correct withWidth
* [typescript] Rename WithWidthEnhancement.
* [typescript] Improve typings for `withStyle`
- add `theme`
- enhanced components has "styled props"
* [typescript] Correct BottomNavigationButton typings
value -> any

Closes #7826
Closes #7830
Closes #7889
Taldrain pushed a commit to Taldrain/material-ui that referenced this issue Aug 24, 2017
…nButton (mui#7897)

* [typescript] Correct withWidth
* [typescript] Rename WithWidthEnhancement.
* [typescript] Improve typings for `withStyle`
- add `theme`
- enhanced components has "styled props"
* [typescript] Correct BottomNavigationButton typings
value -> any

Closes mui#7826
Closes mui#7830
Closes mui#7889
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants