How to Fix "Type 'React.ReactNode' is not assignable to type 'import("...").ReactNode'"?

#Why Does This Happen?

The error you're encountering indicates a conflict between the ReactNode type used in a package and the React.ReactNode type in your project. This discrepancy arises because the package causing the issue expects its own version of ReactNode type, causing conflicts during usage. To illustrate this, consider the following:

import { MyPackageComponent } from 'my-package';

interface MyComponentProps {
  children: React.ReactNode;
}

// Error: Type 'React.ReactNode' is not assignable to type 'import("package-name/node_modules/@types/react/index").ReactNode'.
// Type 'ReactElement<any, string | JSXElementConstructor<any>>' is not assignable to type 'ReactNode'.
// Property 'children' is missing in type 'ReactElement<any, string | JSXElementConstructor<any>>' but required in type 'ReactPortal'.
const MyComponent = ({ children }: MyComponentProps) => (
  <MyPackageComponent>
    {children}
  </MyPackageComponent>
);

The reason "MyPackageComponent" bundles its own version of ReactNode type is most likely because it has a type definition with an import statement that imports ReactNode like so:

// types.ts
import { ReactNode } from 'react';

export interface MyPackageComponentProps {
  children: ReactNode;
}

Due to the import, TypeScript includes the code for ReactNode type in the generated types of the package, leading to the type in the package (wherever the package is used) being referenced like so:

import("package-name/node_modules/@types/react/index").ReactNode

This happens despite the directives in tsconfig.json "exclude" option to exclude types from libraries inside node_modules.

#How to Fix the Issue?

To fix this issue, you can try the following:

  1. Remove import for React.ReactNode

    Instead of importing ReactNode from the react package, you can reference it directly in the interface. This means that, instead of:

    import { ReactNode } from 'react';
    
    export interface MyComponentProps {
      children: ReactNode
      // ...
    }
    

    You should do the following:

    export interface MyComponentProps {
      children: React.ReactNode
      // ...
    }
    

    Since there's no import in the revised code, the ReactNode type is no longer bundled with the generated types for the package.

  2. Set skipLibCheck Option in tsconfig.json

    You can set skipLibCheck option to true, like so:

    // tsconfig.json
    {
      "compilerOptions": {
        "skipLibCheck": true,
        ...
    }
    

    This option proves useful in scenarios where two copies of a library's types exist in "node_modules".

    You should be cautious with this approach, as it skips type checking of declaration files during compilation. As an alternative, you could consider other solutions, such as dependency management tools like yarn resolutions, to avoid conflicts in the first place.


This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.