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

Add witness type for WithStyles<ClassKey> to return value of withStyles() #8829

Closed

Conversation

tvald
Copy link

@tvald tvald commented Oct 24, 2017

Adds a witness type (a field that only exists in TypeScript typings) to the return value of withStyles(), to enable easier typing of React Component props.

Suppose that you have a decorator with many classnames, as returned from withStyles():

const decorate = withStyles<'root0' | 'root1' | 'root2' | 'root3' | 'root4' >(theme => ({
  root0: { overflow: 'hidden' },
  root1: { overflow: 'hidden' },
  root2: { overflow: 'hidden' },
  root3: { overflow: 'hidden' },
  root4: { overflow: 'hidden' },
}))

In order to decorate a React Component, it is necessary to provide the appropriate generic type parameter for the component's props, which is cumbersome when the number of classnames is large:

class Example extends React.Component<MyProps & WithStyles<'root0' | 'root1' | 'root2' | 'root3' | 'root4' >> { ... }
const DecoratedExample = decorate(Example)

The witness type on the decorator carries along the typing information needed to augment component props, dramatically simplifying the React Component definition:

class Example extends React.Component<MyProps & typeof decorate._StyleProps> { ... }
const DecoratedExample = decorate(Example)

@pelotom
Copy link
Member

pelotom commented Oct 25, 2017

One could go even further with this and define something like

type Decorated<P, D extends { _StyleProps: any }> = P & D['_StyleProps'];

// example usage:
decorate(
  class extends React.Component<Decorated<MyProps, typeof decorate>> { ... }
);

or even

class DecoratableComponent<P, D extends { _StyleProps: any }, S = {}>
  extends React.Component<P & D['_StyleProps'], S> {}

// example usage:
decorate(
  class extends DecoratableComponent<MyProps, typeof decorate> { ... }
);

@sebald
Copy link
Member

sebald commented Oct 27, 2017

Hm, I guess this is when typings to start getting kinda weird 😐 I wonder how many people actually think that the exposed property really exists. (Please don't take take this as an personal attack or anything. I bad am at this 😓 )

I wonder how much of an improvement this is over having a class key type:

type ClassKeys = 'root0' | 'root1' | 'root2' | 'root3' | 'root4';

const decorate = withStyles<ClassKeys>(theme => ({
  root0: { overflow: 'hidden' },
  root1: { overflow: 'hidden' },
  root2: { overflow: 'hidden' },
  root3: { overflow: 'hidden' },
  root4: { overflow: 'hidden' },
}));

class Example extends React.Component<MyProps & WithStyles<ClassKeys>> { ... }
const DecoratedExample = decorate(Example)

@oliviertassinari
Copy link
Member

I'm closing this PR as have been inactive for 5 days. Feel free to open a new PR to push the discussion forward. I don't have much optioning on how the TypeScript should be handled. So, I'm gonna let people that know the topic decide. Thanks, everybody.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants