You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用forwardRef的Emotion styled组件TypeScript报错问题求助

React + Emotion styled + forwardRef TypeScript 类型错误解决办法

问题重现

使用Emotion的styled组件包裹forwardRef创建的组件时,出现TypeScript类型不兼容错误:ForwardRefExoticComponent无法赋值给ComponentType,核心原因是两者对组件返回值的类型要求不一致(前者默认返回ReactNode,后者要求返回ReactElement<any, any> | null)。

当前临时方案是使用类型转换styled(Component as FunctionComponent),但这种强制断言方式不符合实际类型逻辑。

相关代码:

import styled from '@emotion/styled';
import React, { forwardRef } from 'react';

type Props = {
  className?: string;
};

const Component = forwardRef<HTMLDivElement, Props>(({ className }, ref) => (
  <div ref={ref} className={className}>
    Component + forwardRef
  </div>
));

const StyledComponent = styled(Component)`
  // Custom styling
`;

对应的TypeScript错误:

No overload matches this call.
  Overload 1 of 6, '(component: ComponentClass<Props & RefAttributes<HTMLDivElement>, any>, options?: StyledOptions<Props & RefAttributes<HTMLDivElement>> | undefined): CreateStyledComponent<...>', gave the following error.
    Argument of type 'ForwardRefExoticComponent<Props & RefAttributes<HTMLDivElement>>' is not assignable to parameter of type 'ComponentClass<Props & RefAttributes<HTMLDivElement>, any>'.
      Type 'ForwardRefExoticComponent<Props & RefAttributes<HTMLDivElement>>' provides no match for the signature 'new (props: Props & RefAttributes<HTMLDivElement>, context?: any): Component<Props & RefAttributes<HTMLDivElement>, any, any>'.
  Overload 2 of 6, '(component: ComponentType<Props & RefAttributes<HTMLDivElement>>, options?: StyledOptions<(Props & RefAttributes<HTMLDivElement>) | (Props & ... 1 more ... & { ...; })> | undefined): CreateStyledComponent<...>', gave the following error.
    Argument of type 'ForwardRefExoticComponent<Props & RefAttributes<HTMLDivElement>>' is not assignable to parameter of type 'ComponentType<Props & RefAttributes<HTMLDivElement>>'.
      Type 'ForwardRefExoticComponent<Props & RefAttributes<HTMLDivElement>>' is not assignable to type 'FunctionComponent<Props & RefAttributes<HTMLDivElement>>'.
        Type 'ReactNode' is not assignable to type 'ReactElement<any, any> | null'.
  Overload 3 of 6, '(tag: keyof IntrinsicElements, options?: StyledOptions<SVGProps<SVGSymbolElement> | DetailedHTMLProps<ObjectHTMLAttributes<HTMLObjectElement>, HTMLObjectElement> | ... 120 more ... | SVGProps<...>> | undefined): CreateStyledComponent<...>', gave the following error.
    Argument of type 'ForwardRefExoticComponent<Props & RefAttributes<HTMLDivElement>>' is not assignable to parameter of type 'keyof IntrinsicElements'.ts(2769)

有效解决方案

方案1:显式指定组件返回类型

给forwardRef包裹的组件明确指定返回类型为React.ReactElement,消除ReactNode与ReactElement的类型歧义:

import styled from '@emotion/styled';
import React, { forwardRef, ReactElement } from 'react';

type Props = {
  className?: string;
};

const Component = forwardRef<HTMLDivElement, Props>(({ className }, ref): ReactElement => (
  <div ref={ref} className={className}>
    Component + forwardRef
  </div>
));

const StyledComponent = styled(Component)`
  padding: 16px;
  background-color: #f5f5f5;
`;

方案2:使用ComponentPropsWithRef定义Props

利用React.ComponentPropsWithRef自动整合原生元素的props和ref属性,让类型推导更顺畅,同时支持扩展自定义属性:

import styled from '@emotion/styled';
import React, { forwardRef, ComponentPropsWithRef } from 'react';

// 基于div的props扩展自定义属性
type Props = ComponentPropsWithRef<'div'> & {
  // 这里可以添加你的自定义props
};

const Component = forwardRef<HTMLDivElement, Props>((props, ref) => {
  const { className, ...restProps } = props;
  return (
    <div ref={ref} className={className} {...restProps}>
      Component + forwardRef
    </div>
  );
});

const StyledComponent = styled(Component)`
  padding: 16px;
  border: 1px solid #eee;
`;

方案3:更严谨的类型断言(不推荐)

如果必须使用类型断言,不要直接断言为FunctionComponent,而是使用更贴合实际的ComponentType,减少类型失真:

const StyledComponent = styled(Component as React.ComponentType<Props & React.RefAttributes<HTMLDivElement>>)`
  // Custom styling
`;

内容的提问来源于stack exchange,提问作者Nadine van Leeuwen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 19:43:15