Skip to content

pciarach/react-import-repro

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@emotion/styled type declarations rely on UMD global React — breaks StyledComponent when project declares const React

TL;DR

@emotion/styled/dist/declarations/src/types.d.ts (and @emotion/react's equivalent) use React.FC, React.ComponentClass, React.ComponentProps, React.JSX.*, etc. with no React import — they silently rely on the UMD global that @types/react exposes via export as namespace React.

That assumption breaks as soon as a project declares const React: typeof import('react') (a common pattern for SSR hydration or legacy script interop). The value binding shadows the UMD type namespace, StyledComponent extends React.FC<...> loses its call signature, and every styled component becomes unusable as a JSX element:

error TS2604: JSX element type 'Separator' does not have any construct or call signatures.
error TS2786: 'Separator' cannot be used as a JSX component.
  Its type 'StyledComponent<...>' is not a valid JSX element type.

Reproduce

npm install
npx tsc --noEmit

Expected output — one TS2604+TS2786 pair per <X /> usage in src/repro.tsx.

What triggers it

Two files combine to produce the error:

  1. src/repro.tsx — creates styled components via @emotion/styled and renders them as JSX elements.
  2. src/global.d.ts — declares a global React variable:
    type ReactNamespace = typeof import('react');
    declare namespace globalThis {
        var React: ReactNamespace;
    }
    This pattern is common in projects that expose React on window/globalThis. Many real-world apps have something like it.

Delete src/global.d.ts and the errors disappear — the UMD global is no longer shadowed, so React.FC resolves correctly again. But the underlying reliance on the UMD global is still a fragile assumption.

Diagnosis

@emotion/styled/dist/declarations/src/types.d.ts imports:

import { ComponentSelector, Interpolation } from '@emotion/serialize';
import { ReactJSXIntrinsicElements } from "./jsx-namespace.js";
import { PropsOf, Theme } from '@emotion/react';
// no React import

Yet uses React.* throughout:

interface StyledComponent<...> extends React.FC<...>, ComponentSelector { ... }
//                                       ^^^^^ relies on UMD global

@emotion/react/dist/declarations/src/types.d.ts and jsx-namespace.d.ts have the same pattern.

These files depend on export as namespace React from @types/react making React available as a global. When a project declares var React: typeof import('react'), that value declaration shadows the namespace. React.FC then resolves against the value's type rather than the namespace, the inherited call signature is lost, and TypeScript reports the JSX errors above.

Fix

Add an explicit import * as React from 'react' to types.d.ts and jsx-namespace.d.ts instead of relying on the UMD global. The UMD path is fragile and breaks as soon as any ambient var React is in scope.

Environment

  • @emotion/styled@11.14.1, @emotion/react@11.14.0
  • @types/react@18.3.28, react@18.3.1
  • typescript@6.0.2
  • tsconfig.compilerOptions: jsx: "react", strict: true, moduleResolution: "bundler", skipLibCheck: true

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors