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

React+styled-components+TypeScript中BEM风格命名的类型错误求助

Fixing TypeScript Errors with BEM-like Styled Components in React

Got it, let's fix those TypeScript errors you're seeing with your BEM-like styled-components setup. The root issue is that TypeScript doesn't automatically know about the static header property you're adding to your Card component—we need to explicitly define custom types to make this work properly.

Here's a step-by-step solution:

Step 1: Define Custom Types for Your Card Component

First, create interfaces and types to describe the full shape of your Card component, including its sub-components. This tells TypeScript exactly what properties to expect on the Card object.

import styled from 'styled-components';

// 1. Define the structure of your Card's sub-components
interface CardSubComponents {
  header: typeof Header;
  // Add other sub-components here (e.g., footer, content) if needed
}

// 2. Create a combined type that merges the base styled component with our sub-components
type CardComponent = typeof CardContainer & CardSubComponents;

Step 2: Build Your Base Card Container and Sub-Components

Create your core Card container and its sub-components like you normally would with styled-components:

// Base Card container
const CardContainer = styled.div`
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  padding: 1.5rem;
  max-width: 400px;
`;

// Header sub-component (BEM-like Card__header)
const Header = styled.h1`
  font-size: 1.25rem;
  margin: 0 0 1rem 0;
  color: #333;
`;

Step 3: Attach Sub-Components to the Base Card

Cast the base CardContainer to our custom CardComponent type, then attach the sub-component. This resolves the "Type 'StyledComponent<...>' is not assignable to type 'never'" error.

// Cast the container to our custom type to enable adding sub-components
const Card = CardContainer as CardComponent;
Card.header = Header;

// Export the complete Card component
export default Card;

Step 4: Use the Component in App.tsx

Now you can use <Card.header> without the "JSX element type 'Card.header' does not have any construct or call signatures" error:

import Card from './card';

function App() {
  return (
    <div style={{ padding: '2rem' }}>
      <Card>
        <Card.header>Header</Card.header>
        <p>Card content goes here</p>
      </Card>
    </div>
  );
}

export default App;

Why This Works

  • The CardSubComponents interface explicitly declares that our Card component has a header property matching the type of our Header styled component.
  • The CardComponent type merges the base styled component type with our sub-components interface, so TypeScript recognizes both the component itself and its static properties.
  • Casting CardContainer to CardComponent allows us to safely attach sub-components without TypeScript throwing type mismatch errors.

If you need to add more sub-components (like Card.footer or Card.content), just extend the CardSubComponents interface and repeat the attachment step.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 10:42:30