Skip to content

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

Closed

Description

@bytenik

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.

Activity

  1. rhys-vdw commented on Dec 2, 2018

    @rhys-vdw
    Contributor

    This may explain this one: #28768 (comment)

  2. weswigham commented on Dec 4, 2018

    @weswigham
    Member

    Thanks for the link Rhys van der Waerden (@rhys-vdw) - that is indeed the case.

  3. weswigham commented on Dec 4, 2018

    @weswigham
    Member

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

  4. bytenik commented on Dec 5, 2018

    @bytenik
    Author

    Wesley Wigham (@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+.

  5. weswigham commented on Dec 5, 2018

    @weswigham
    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.

  6. typescript-bot commented on Dec 12, 2018

    @typescript-bot
    Contributor

    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.

  7. bytenik commented on Jan 27, 2019

    @bytenik
    Author

    Wesley Wigham (@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.

  8. weswigham commented on Jan 27, 2019

    @weswigham
    Member

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

  9. bytenik commented on Jan 28, 2019

    @bytenik
    Author

    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.

  10. gsbelarus commented on Jan 28, 2019

    @gsbelarus

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

  11. eggers commented on May 12, 2019

    @eggers

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

  12. gamebox commented on Oct 28, 2019

    @gamebox

    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.

  13. pinkbunny1 commented on Nov 22, 2019

    @pinkbunny1

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

  14. bytenik commented on Nov 22, 2019

    @bytenik
    Author

    I still routinely run into this.

  15. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions