Skip to content

TS 3.2 breaks type-unioned component support under certain circumstances #28795

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

Closed
bytenik opened this issue Dec 1, 2018 · 14 comments
Closed
Labels
Duplicate An existing issue was already created

Comments

@bytenik
Copy link

bytenik commented Dec 1, 2018

TypeScript Version: 3.3.0-dev.20181129

Code

ex.tsx:

import * as React from 'react';
import {BrowserRouter, HashRouter, Redirect, Route, RouteProps, Switch} from 'react-router-dom';

type State = {SelectedRouter?: typeof BrowserRouter | typeof HashRouter};
export class Example extends React.Component<{}, State> {
    state: State = {};
    render() {
        const {SelectedRouter} = this.state;
        if (!SelectedRouter) return null;
        return <><SelectedRouter>asdf</SelectedRouter></>;
    }
}

package.json:

{
  "name": "temp",
  "version": "1.0.0",
  "description": "",
  "author": "",
  "license": "ISC",
  "dependencies": {},
  "devDependencies": {
    "@types/prop-types": "^15.5.6",
    "@types/react": "^16.7.11",
    "@types/react-dom": "^16.0.11",
    "@types/react-router": "^4.0.32",
    "@types/react-router-dom": "^4.3.1",
    "csstype": "^2.5.7",
    "typescript": "^3.3.0-dev.20181129"
  }
}

tsconfig.json:

{
    "compilerOptions": {
      "lib": [ "dom", "es2015" ],
      "module": "es2015",
      "moduleResolution": "node",
      "target": "es6",
      "jsx": "react",
    },
    "include": [ "*.tsx" ]
}

Expected behavior:

Successful compilation.

Actual behavior:

ex.tsx:10:19 - error TS2604: JSX element type 'SelectedRouter' does not have any construct or call signatures.

10         return <><SelectedRouter>asdf</SelectedRouter></>;
                     ~~~~~~~~~~~~~~


Found 1 error.

Notes:
This works with TypeScript 3.1.x, but breaks with 3.2.0+. I am not clear on why certain types work and certain types do not, but I imported the React Router types because they definitely break. I tried creating a test ComponentA and ComponentB with a render function that returns null, but using a union of typeof ComponentA | typeof ComponentB compiles successfully for some reason.

@rhys-vdw
Copy link
Contributor

rhys-vdw commented Dec 2, 2018

This may explain this one: #28768 (comment)

@weswigham
Copy link
Member

Thanks for the link @rhys-vdw - that is indeed the case.

@weswigham
Copy link
Member

I'm going to mark this as a duplicate of #7294 - go chime in how important that is there, thanks~

@weswigham weswigham added the Duplicate An existing issue was already created label Dec 4, 2018
@bytenik
Copy link
Author

bytenik commented Dec 5, 2018

@weswigham I'm not sure how it can be the same problem. #7294 has been an issue since 2016, whereas the issue I'm describing only began with 3.2+.

@weswigham
Copy link
Member

With 3.2 we merged jsx resolution and normal call resolution. (Previously they were separate but similar) To deal with unions, jsx call resolution was doing some unsafe operations that could poison some caches with invalid types and had been the source of a fair set of other bugs in the jsx implementation, especially surrounding generics.

We do intend to fix it - I'm just saying we already have a more general issue tracking the problem, since the problem extends beyond jsx tags to all kinds of calls.

@typescript-bot
Copy link
Collaborator

This issue has been marked as a duplicate and has seen no activity in the last day. It has been closed automatic house-keeping purposes.

@bytenik
Copy link
Author

bytenik commented Jan 27, 2019

@weswigham This issue persists in 3.3.0-rc. Is this still a dupe of #7294? That one is closed and supposed to be fixed in 3.3.

@weswigham
Copy link
Member

weswigham commented Jan 27, 2019

Do BrowserRouter and HashRouter both have overloads or generic arguments? We still can't resolve union calls on unions of multiple generic signatures.

@bytenik
Copy link
Author

bytenik commented Jan 28, 2019

Yep, they both have generic arguments.

Would it be appropriate to reopen this issue then? Or is there another issue tracking this, or a workaround for now? Fingers crossed for a workaround for now at least because my team is pinned to 3.1.x until we can resolve it.

@gsbelarus
Copy link

Also waiting at least for work around, although there is always retreat to typecast.

@eggers
Copy link

eggers commented May 12, 2019

Can we reopen this issue? The related ticket is closed, but this problem still persists in 3.4.x

@gamebox
Copy link

gamebox commented Oct 28, 2019

I'm seeing a very similar issue as well with @types/react at ^16.9.5 and typescript at ^3.6.4.

I have a union like the following:

type ComponentUnion =
  | React.Component<SomePropType>
  | React.FunctionComponent<SomePropType>;

This fails with the above error. Removing the union and using ComponentUnion as just a type alias for one works as expected.

@pinkbunny1
Copy link

Since it is a class component, it should be declared with ComponentClass as export class Example extends React.Component<{}, State>

@bytenik
Copy link
Author

bytenik commented Nov 22, 2019

I still routinely run into this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

8 participants