preactjs / preact

⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.
https://preactjs.com
MIT License
36.49k stars 1.94k forks source link

Preact 10.0.1 types not compatible with React-Redux 7.1.1? #2024

Open AlexReff opened 4 years ago

AlexReff commented 4 years ago

After setting noImplicitAny: true in my project, I realized I was missing the type declarations for react-redux. After running npm i -D @types/react-redux, I now get the following error on all of my components that use react-redux's connect

Argument of type 'typeof MY_COMPONENT' is not assignable to parameter of type 'ComponentType<never>'.
  Type 'typeof MY_COMPONENT' is not assignable to type 'ComponentClass<never, any>'.
    Types of property 'contextType' are incompatible.
      Type 'preact.Context<any>' is not assignable to type 'React.Context<any>'.
        Types of property 'Provider' are incompatible.
          Property '$$typeof' is missing in type 'Provider<any>' but required in type 'ProviderExoticComponent<ProviderProps<any>>'.ts(2345)
index.d.ts(318, 18): '$$typeof' is declared here. (Points to @types/react because of the dependency listed for @types/react-redux)
        "preact": "^10.0.1",
        "react-redux": "^7.1.1",
        "redux": "^4.0.4",
        "@types/react-redux": "^7.1.5",

Shortened example:

import { Component, h } from "preact";
import { connect } from "react-redux";

class MY_COMPONENT extends Component<IProps, IState> {
....
}

export default connect(mapStateToProps, mapDispatchToProps)(MY_COMPONENT); //error on MY_COMPONENT

I've googled this as much as I can and have not found any answers. I don't see $$typeof anywhere in Preact's index.d.ts file.

My tsconfig.json is:

{
    "compilerOptions": {
        "outDir": "./dist",
        "sourceMap": true,
        "noImplicitAny": true,
        "suppressImplicitAnyIndexErrors": true,
        "experimentalDecorators": true,
        "module": "commonjs",
        "target": "es6",
        "lib": [
            "es2015",
            "es2017",
            "dom"
        ],
        "allowJs": true,
        "removeComments": true,
        "allowSyntheticDefaultImports": true,
        "resolveJsonModule": true,
        "esModuleInterop": true,
        "jsx": "react",
        "baseUrl": "./",
        "jsxFactory": "h"
    },
    "exclude": ["node_modules", "dist", "deprecated"]
}
38elements commented 4 years ago

How about trying to use preact-redux? https://github.com/developit/preact-redux

AlexReff commented 4 years ago

If you're using Preact X (preact@10+), please use the official react-redux library.

AlexReff commented 4 years ago

Update: it looks as though the core issue might be the type definition of @types/react-redux's connect function.

I have not encountered any actual functional bugs outside of this type 'mismatch'

See: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/19989

Workarounds:

If you still need other typings for react-redux, just cast as any wherever needed.

Otherwise,

A) set noImplicitAny to false in your tsconfig.json

or

B) create a declarations.d.ts file with the line declare module "react-redux"; in it, and remove @types/react-redux entirely.

38elements commented 4 years ago

How about trying to use preact/compat?

AlexReff commented 4 years ago

I don't believe there is a connect function exported in preact/compat - and using Component from preact/compat doesn't change this outcome. I think the issue lies with @types/react-redux and not with preact itself.

ForsakenHarmony commented 4 years ago

Have you tried aliasing react to preact in the typescript config as well?

birjj commented 4 years ago

Can confirm that @ForsakenHarmony's suggestion works. Your tsconfig should look a little something like this:

{
  "compilerOptions": {
    // ...
    "baseUrl": ".",
    "paths": {
      "react": ["node_modules/preact/compat"],
      "react-dom": ["node_modules/preact/compat"]
    }
  }
}
brandonros commented 2 years ago
      import * as Preact from 'https://unpkg.com/preact?module'
      import htm from 'https://unpkg.com/htm?module'
      const html = htm.bind(Preact.createElement)

      import * as reactRedux from 'https://unpkg.com/react-redux?module'

Is something like this possible? (no typescript, no rollup, etc.)

https://github.com/preactjs/preact/issues/3469