使用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
相关产品推荐
相关产品推荐

