diff --git a/.storybook/src/v4.0.0.mdx b/.storybook/src/v4.0.0.mdx
index e7f473751..a6fd32dee 100644
--- a/.storybook/src/v4.0.0.mdx
+++ b/.storybook/src/v4.0.0.mdx
@@ -121,6 +121,25 @@ After
```
+### ButtonのGeneric propsについて
+
+[Styled Componentの制限](https://github.com/styled-components/styled-components/issues/1803)により`styled(Button)`で拡張する場合propsがうまく推論されない場合があります。
+Charcoal v4.1.0から過剰なpropsを検出する処理を追加したが、`component` propと合わせて使う時の型を配慮する必要があります。
+
+サンプル
+
+```tsx
+// allow component
+const StyledButton = styled(Button)`` as typeof Button
+
+
+// preserve component type
+const StyledButtonA = styled(Button<'a'>)``
+
+```
+
+その他のケースは [styledButtonTypeTest.d.tsx](https://github.com/pixiv/charcoal/blob/main/packages/react/src/components/Button/styledButtonTypeTest.d.tsx) を参考してください。
+
## Checkbox
- `Checkbox`の`input`要素を`children`がない場合に label で囲わないようにしました。
diff --git a/packages/react/src/components/Button/index.tsx b/packages/react/src/components/Button/index.tsx
index d36be7078..677cb04f9 100644
--- a/packages/react/src/components/Button/index.tsx
+++ b/packages/react/src/components/Button/index.tsx
@@ -46,5 +46,11 @@ const Button = forwardRef(function Button(
ref={ref}
/>
)
-}) as (p: ButtonProps) => JSX.Element
+}) as (
+ p: 'button' extends T
+ ? ButtonProps<'button'>
+ : ButtonProps & {
+ component: T // required
+ }
+) => JSX.Element
export default Button
diff --git a/packages/react/src/components/Button/styledButtonTypeTest.d.tsx b/packages/react/src/components/Button/styledButtonTypeTest.d.tsx
new file mode 100644
index 000000000..3680ae693
--- /dev/null
+++ b/packages/react/src/components/Button/styledButtonTypeTest.d.tsx
@@ -0,0 +1,81 @@
+// This file is for type testing only
+
+// only use the type
+import type { default as ButtonType } from './index'
+import type styledType from 'styled-components'
+
+declare const Button: typeof ButtonType
+declare const styled: typeof styledType
+
+const Custom = ({ custom }: { custom: string }) => <>{custom}>
+const CustomGeneric = ({ custom }: { custom: C }) => (
+ <>{custom}>
+)
+
+const StyledButton = styled(Button)``
+const StyledButtonAsButton = styled(Button<'button'>)``
+const StyledButtonA = styled(Button<'a'>)``
+const StyledButtonCustom = styled(Button)``
+const StyledButtonCustomAsButton = styled(
+ Button
+)`` as typeof Button
+const StyledButtonCustomGeneric = styled(Button)``
+const StyledButtonCustomGenericFoo = styled(
+ Button>
+)``
+
+// for type test only
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+function Tests() {
+ return (
+ <>
+ {/* OK */}
+
+
+
+
+
+
+ component="a" href="#" />
+ >
+ component={CustomGeneric}
+ custom="bar"
+ />
+
+
+
+ }
+ custom="foo"
+ />
+
+ {/* NG */}
+
+ {/* @ts-expect-error Property 'href' does not exist on type */}
+
+ {/* @ts-expect-error Property 'href' does not exist on type */}
+
+ {/* @ts-expect-error Property 'component' is missing */}
+
+ {/* @ts-expect-error Property 'disabled' does not exist on type */}
+
+ {/* @ts-expect-error Type '"button"' is not assignable to type '"a"' */}
+
+ {/* @ts-expect-error Property 'component' is missing */}
+
+ {/* @ts-expect-error Type 'string' is not assignable */}
+
+ {/* @ts-expect-error Property 'custom' does not exist on type */}
+
+ {/* @ts-expect-error Type 'href' is not assignable */}
+ href="#" />
+ }
+ custom="foo"
+ />
+ {/* @ts-expect-error '""' is not assignable to type '"foo"' */}
+
+ >
+ )
+}