question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[typescript] React.ReactElement type is not compatible with Preact and prevents interoperability with React

See original GitHub issue

There is a type mismatch between React.ReactElement and preact.VNode that prevents usage of typescript/react code with typescript/preact.

While the code below compiles and works without an issue, Typescript typechecking fails.

Reproduction

import type React from 'react'
import { FunctionalComponent, h } from 'preact'

const ReactFCInterlop: React.FC = () => {
    return <span>hello</span>
}

const Home: FunctionalComponent = () => {
    return (
        <div>
            <ReactFCInterlop /> // this fails to typecheck
        </div>
    )
}

export default Home

This results in the following typescript error:

$ tsc
src/routes/home/index.tsx:11:14 - error TS2786: 'ReactFCInterlop' cannot be used as a JSX component.
  Its return type 'ReactElement<any, any> | null' is not a valid JSX element.
    Type 'ReactElement<any, any>' is missing the following properties from type 'Element': nodeName, attributes, children

11             <ReactFCInterlop />
                ~~~~~~~~~~~~~~~

Typescript config:

$ tsc --showConfig
{
    "compilerOptions": {
        "skipLibCheck": true,
        "target": "es5",
        "module": "esnext",
        "allowJs": true,
        "jsx": "preserve",
        "jsxFactory": "h",
        "noEmit": true,
        "strict": true,
        "moduleResolution": "node",
        "esModuleInterop": true
    },
    "files": [
        "./src/components/app.tsx",
        "./src/components/header/index.tsx",
        "./src/routes/home/index.tsx",
        "./src/routes/notfound/index.tsx",
        "./src/routes/profile/index.tsx",
        "./src/tests/header.test.tsx",
        "./src/types.d.ts",
        "./src/components/header/style.css.d.ts",
        "./src/routes/home/style.css.d.ts",
        "./src/routes/notfound/style.css.d.ts",
        "./src/routes/profile/style.css.d.ts",
        "./src/tests/declarations.d.ts"
    ],
    "include": [
        "src/**/*.tsx",
        "src/**/*.ts"
    ]
}

Deps:

$ npm ls --depth 0 | grep preact
├── enzyme-adapter-preact-pure@2.2.3
├── jest-preset-preact@4.0.2
├── preact@10.4.8
├── preact-cli@3.0.1
├── preact-jsx-chai@3.0.0
├── preact-markup@2.0.0
├── preact-render-to-string@5.1.10
├── preact-router@3.2.1

Tested with Typescript: 4.0.2 / 3.9.7

Expected Behavior

Preact should be able to interlope with components that use typescript and @types/react. There a lot of components like that.

Workaround

This is a very dumb workaround, but it works:

// src/types.d.ts
import React from 'react'

declare global {
    namespace React {
        interface ReactElement {
            nodeName: any
            attributes: any
            children: any
        }
    }
}

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:15
  • Comments:17 (7 by maintainers)

github_iconTop GitHub Comments

12reactions
Satyamcommented, May 10, 2022

May I suggest that this issue is marked as a documentation issue by adding @Svampen fix to the Typescript Configuration section in the docs.

@Svampen suggests above adding the following to tsconfig.json:

  {
    "baseUrl": "./",
    "paths": {
      "react": ["./node_modules/preact/compat/"],
      "react-dom": ["./node_modules/preact/compat/"]
    }

The paths are relative to the baseUrl so if you change that, which you might, you must change the paths accordingly, for example, if you have "baseUrl":"./src" then your paths would start with ../node_modules (double-dot).

You have no control over what and how other imported packages and their dependencies reference and cause @types/react to be installed. Any potential developer who adds @types/react as a dependency instead of a peerDependency in their package.json will cause the same issue. It might be Enzyme or, as it is my case, a dependency of a dependency of react-bootstrap but it might be anything else in the future, you have no control over that.

Whichever way it gets loaded, once it is, you are in trouble. By equating the paths to react and react-dom to preact/compat through tsconfig.json, it doesn’t matter which dependent package imports those definitions, it won’t even look at @types/react even if it does get installed into node_modules, it will simply be ignored.

2reactions
JoviDeCroockcommented, Jun 3, 2022

This has been added to the dos in https://github.com/preactjs/preact-www/pull/850 thank you @satyam

Read more comments on GitHub >

github_iconTop Results From Across the Web

TypeScript | Preact: Fast 3kb React alternative with the same ...
There are different ways to type components in Preact. Class components have generic type variables to ensure type safety. TypeScript sees a function...
Read more >
Fixing JSX types between Preact and React Libraries
How to fix JSX TypeScript errors due to incompatible types between Preact and imported React component libraries, especially for JSX.
Read more >
NPM package cannot be used as a JSX Component
The types returned by 'render()' are incompatible between these types. Type 'React.ReactNode' is not assignable to type 'import("/home/user/app/ ...
Read more >
Try React 17 now— learn what's new in v17 and what does it ...
React is maturing and it is now on version 16.x, version 17 is expected to come out ... React itself as well as...
Read more >
warning: [antd: form.item] `name` is only used for validate react ...
Item] name is only used for validate React element. ... Because we have adjusted the minimum requirements for compatibility, ... Stop IE9/10 support....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found