Skip to content

Correct typings for themr #39

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

Merged
merged 5 commits into from
Jan 20, 2017
Merged

Correct typings for themr #39

merged 5 commits into from
Jan 20, 2017

Conversation

odensc
Copy link
Contributor

@odensc odensc commented Dec 24, 2016

No description provided.

@mpodlasin
Copy link

mpodlasin commented Dec 30, 2016

Hi.
@TheSBros Are those working for you? With TS 2.1, using these typings if I declare state of my decorated component to something else than void | {}, I get following error:


ERROR in ./src/components/NewTask/NewTask.tsx
(19,1): error TS1238: Unable to resolve signature of class decorator when called as an expression.
  Type 'ThemedComponent<NewTaskProps>' is not assignable to type 'typeof NewTask'.
    Type 'Component<NewTaskProps, ComponentState>' is not assignable to type 'NewTask'.
      Types of property 'state' are incompatible.
        Type 'ComponentState' is not assignable to type '{ state: string; }'.
          Type 'void' is not assignable to type '{ state: string; }'.

It is happening because in definition of React.ComponentClass state is defined precisely as void | {}, which makes sense, since you do not want to expose definition of your state externally, but in this case it results in error.

Thanks in advance and have great day!

@javivelasco
Copy link
Owner

Can anybody confirm this update is properly done to merge?

@odensc
Copy link
Contributor Author

odensc commented Jan 6, 2017

Just commited a fix. Let me know if it works @Podlas29.

Only caveat is calling getWrappedInstance() won't return the type of the original component, it will return React.Component<OriginalP, OriginalS>. You can still cast it to the correct type. If you know how to fix that @Podlas29, tell me :)

export function themr(
identifier: string,
defaultTheme?: {},
options?: IThemrOptions
);
): <P, S>(component: new() => React.Component<P, S>) => ThemedComponentClass<P, S>;
Copy link

@mpodlasin mpodlasin Jan 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still will not work if component accepts some props or context through constructor.

consturctor(props: MyProps) {}

Adding

new(props?: P, context?: any)

will help.
After that for me it works perfect.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed. :)

@mpodlasin
Copy link

Well I did get around all problems (both state type and wrong instance being returned in getWrappedComponent with following code:

interface ThemedComponent<P, S, Base> extends React.Component<P, S> {
    getWrappedInstance(): Base;
}

interface ThemedComponentClass<P, S, Base> extends React.ComponentClass<P> {
    new(props?: P, context?: any): ThemedComponent<P, S, Base>;
}

export interface Themr {
    (
        identifier: string,
        defaultTheme?: {},
        options?: IThemrOptions
    ): <P, S, C extends new(props?: P, context?: any) => React.Component<P, S>>
        (component: C) => ThemedComponentClass<P, S, C>;
}

It got really ugly thought. ;)

@odensc
Copy link
Contributor Author

odensc commented Jan 6, 2017

It got really ugly thought.

That's fine, it seems to be the only way to do it. I tried something like that but couldn't get it working.

Thanks, updated with your code. Look good?

@mpodlasin
Copy link

mpodlasin commented Jan 6, 2017

One more thing - I just do not know - is it OK to pass stateless components to themr decorator? If so, I would add such possibility to typings.

@odensc
Copy link
Contributor Author

odensc commented Jan 6, 2017

I'm not sure, - @javivelasco would have to confirm. However you can't even use decorators on functions; such as a stateless component.

@mpodlasin
Copy link

Well decorator is simply a function. In mobx for example you can use both

@observer
class Component extends React.Component ...

and

observer(props => ...)

In our case it would be

themr('MyName')(props => ...)

Much cleaner if you do not need state.

@odensc
Copy link
Contributor Author

odensc commented Jan 6, 2017

That's true, looking at the code I'm not sure if it would work with stateless components.. We'll have to see.

@mpodlasin
Copy link

mpodlasin commented Jan 6, 2017

@TheSBros Also my code seems problematic as well - typescript is unable to infer P and S and assumes they are {} which makes adding props to decorated component impossible.
Currently your version (before last commit) seems to be the best. Casting wrappedInstance is probably better then explicitly typing every decorated component.

@javivelasco
Copy link
Owner

@Podlas29 You can use the decorator in a functional component but the legacy syntax is valid only for classes. At the end it's just a function returning another function

@odensc
Copy link
Contributor Author

odensc commented Jan 12, 2017

@javivelasco should be ready to merge now. Would recommend to squash to clean up the mess.

@javivelasco javivelasco merged commit 073cd89 into javivelasco:master Jan 20, 2017
@javivelasco
Copy link
Owner

Thanks!

@odensc odensc mentioned this pull request Feb 14, 2017
raveclassic added a commit to raveclassic/react-css-themr that referenced this pull request Feb 14, 2017
@raveclassic
Copy link
Contributor

raveclassic commented Feb 14, 2017

Seems like now there's a conflict with render method when strictNullChecks flag is set:

@themr('foo') //error - Type 'null' is not assignable to type 'Element'
class FooClass extends React.Component<any, any> {
	render()/*: JSX.Element | null //ok when uncommented*/ {
		return <div>hi</div>;
	}
}

@raveclassic
Copy link
Contributor

Moreover, decorating a class with @themr complains on every lifecycle method (like componentWillMount) of decorating class as TS can't cast it to as ComponentClass. On the other hand, calling themr as a function on existing class works fine - seems like decorators are broken in TS.

javivelasco pushed a commit that referenced this pull request Feb 20, 2017
* refactoring

* theme spreads

* typings

* fix themr typing

* fix themr typing

* fix undefined mixin value cases

* fix state type incompatibility in #39

* revert typing changes

* accept sfc as component

* typo

* also accept symbols and numbers as identifier

* merge sfc fix
david-slayte pushed a commit to david-slayte/react-css-themr that referenced this pull request Jul 6, 2018
* Correct typings for `themr`

* Fixed decorator usage

* Update index.d.ts

* Updated with better typings from @Podlas29

* Revert to working state
david-slayte pushed a commit to david-slayte/react-css-themr that referenced this pull request Jul 6, 2018
* refactoring

* theme spreads

* typings

* fix themr typing

* fix themr typing

* fix undefined mixin value cases

* fix state type incompatibility in javivelasco#39

* revert typing changes

* accept sfc as component

* typo

* also accept symbols and numbers as identifier

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

Successfully merging this pull request may close these issues.

4 participants