#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:
-
Remove
import
forReact.ReactNode
Instead of importing
ReactNode
from thereact
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, theReactNode
type is no longer bundled with the generated types for the package. -
Set
skipLibCheck
Option intsconfig.json
You can set
skipLibCheck
option totrue
, 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.