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

如何在styled-components中动态切换图标?解决ThemeProps类型报错问题

Hey there! Let's figure out how to fix that styled-components error you're seeing, plus get dynamic icon switching working smoothly.

Fixing "Property 'icon' does not exist on type 'ThemeProps'" & Enabling Dynamic Icons

Why you're hitting this error

TypeScript enforces strict type checking, and by default, styled-components' props are typed as ThemeProps<DefaultTheme>—which only includes the theme property. Your custom icon prop isn't recognized in this default type, hence the error. Also, there's a small mix-up in your code: you named the props parameter Icon (that's confusing, since it's not an icon component—it's the entire props object passed to your input).

Step-by-step solution

1. Define a type for your component's props

First, create an interface to tell TypeScript about your custom icon prop (make it optional so the input works with or without an icon):

interface GenericInputProps {
  icon?: string;
}

2. Update your styled component with the correct type

Pass this interface to styled.input so TypeScript recognizes the icon prop, and fix the props parameter name for clarity:

import styled, { css } from 'styled-components';

interface GenericInputProps {
  icon?: string;
}

export const GenericInput = styled.input<GenericInputProps>`
  background-color: #f4f4f4;
  width: 220px;
  height: 47px;
  border: none;
  border-radius: 50px;
  font-weight: 600;
  font-size: 16px;
  cursor: pointer;
  letter-spacing: 1px;
  padding: 15px 30px;
  -moz-outline-radius: 50px;
  outline: none;

  ${({ icon }) => icon && css`
    background-image: url(${icon});
    background-size: 20px;
    background-position: 10px 50%;
    background-repeat: no-repeat;
    color: #c7c7c7;
    /* Add left padding so text doesn't overlap the icon */
    padding-left: 50px;
  `}

  ::placeholder {
    color: #c7c7c7;
  }
`;

Pro tip: I added padding-left: 50px when the icon is present—this keeps your input text from overlapping the icon, which is a quick UI polish.

3. Switch icons dynamically

Now you can pass different icon URLs to the component to toggle them on the fly. Here's an example in a React component:

import { useState } from 'react';
import { GenericInput } from './path-to-your-component';

function App() {
  // Start with a default icon
  const [currentIcon, setCurrentIcon] = useState('/icons/user-profile.svg');

  // Toggle between two icons when a button is clicked
  const switchIcon = () => {
    setCurrentIcon(prev => 
      prev === '/icons/user-profile.svg' ? '/icons/search-magnifier.svg' : '/icons/user-profile.svg'
    );
  };

  return (
    <div>
      <GenericInput icon={currentIcon} placeholder="Enter text here..." />
      <button onClick={switchIcon}>Swap Icon</button>
    </div>
  );
}

If you just want to bypass the type check quickly (great for testing), you can use any for the props type:

export const GenericInput = styled.input<any>`
  // ... rest of your existing code
  ${({ icon }) => icon && css`
    // ... icon styles
  `}
`;

But using proper TypeScript types is way better for long-term maintainability.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 23:37:47