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

如何为Styled-Components组合正确编写TypeScript接口?解决接口扩展相关TypeScript报错

解决Styled Components组合组件的TypeScript接口报错问题

你遇到的这个报错,核心原因是React.ComponentType是一个联合类型(包含函数组件和类组件的类型),TypeScript不允许接口直接继承这种动态的联合类型——接口只能继承有静态已知成员的对象类型。下面是两种可行的解决方案:

方案一:利用typeof和交叉类型直接定义组合类型

这种方式最简洁,不需要额外定义接口,直接通过typeof获取基础styled组件的原生类型,再结合静态属性的类型做交叉:

import styled from "styled-components";

const Title = styled.div``;
const TitleNumber = styled.div``;
const TitleNumberDigit = styled.div``;
const TitleName = styled.div``; // 无需手动指定React.ComponentType,styled已返回正确类型

// 定义Number组件的类型:基础styled组件类型 + Digit静态属性
type UiStepTitleNumber = typeof TitleNumber & {
  Digit: typeof TitleNumberDigit;
};

// 定义整体Title组件的类型:基础styled组件类型 + Number和Name静态属性
type UiStepTitle = typeof Title & {
  Number: UiStepTitleNumber;
  Name: typeof TitleName;
};

const UiStepTitle: UiStepTitle = Object.assign(Title, {
  Number: Object.assign(TitleNumber, {
    Digit: TitleNumberDigit,
  }),
  Name: TitleName,
});

export default UiStepTitle;

方案二:定义包含调用签名的接口

如果你更倾向于用接口来规范类型,可以通过调用签名模拟组件的可调用特性,再结合静态属性:

import styled from "styled-components";
import type { ReactNode } from "react";

const Title = styled.div``;
const TitleNumber = styled.div``;
const TitleNumberDigit = styled.div``;
const TitleName = styled.div``;

interface IUiStepTitleNumber {
  // 模拟组件的调用签名,匹配基础组件的props类型
  (props: React.ComponentProps<typeof TitleNumber>): React.ReactElement;
  Digit: typeof TitleNumberDigit;
}

interface IUiStepTitle {
  (props: React.ComponentProps<typeof Title>): React.ReactElement;
  Number: IUiStepTitleNumber;
  Name: typeof TitleName;
}

const UiStepTitle: IUiStepTitle = Object.assign(Title, {
  Number: Object.assign(TitleNumber, {
    Digit: TitleNumberDigit,
  }),
  Name: TitleName,
});

export default UiStepTitle;

补充说明

原来的写法报错,本质是React.ComponentType<P>是React.FunctionComponent<P> | React.ClassComponent<P>的别名——属于联合类型。TypeScript的接口继承要求目标类型必须是结构明确的对象类型,联合类型不符合这个规则,所以才会抛出An interface can only extend an object type or intersection of object types with statically known members的错误。

上面两种方案都避开了直接继承ComponentType,而是通过交叉类型或调用签名保留了组件的可调用性,同时正确添加了静态属性的类型定义,修改后你原来的JSX用法就能正常工作,且TypeScript不会再报错。

内容的提问来源于stack exchange,提问作者Undermuz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 07:49:08