Reputation: 28086
I would like a simple component that I can style and pass a prop the output
element type with as
. Using version 5
of styled-components
and 4
for TS
However I get the following TS error
No overload matches this call.
Overload 1 of 2, '(props: Omit<Omit<Pick<DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, "key" | keyof HTMLAttributes<...>> & { ...; }, never> & Partial<...>, "theme"> & { ...; } & { ...; }): ReactElement<...>', gave the following error.
Type 'string' is not assignable to type 'undefined'.
This JSX tag's 'children' prop expects type 'never' which requires multiple children, but only a single child was provided. TS2769
11 | color: #000;
12 | `
> 13 | return <Component as={as}>{children}</P>
| ^
14 | }
15 |
The key part of this error is here I believe Type 'string' is not assignable to type 'undefined'.
However my understanding was that with the {as = 'p'}
this was the default value for as
?
import React, { ReactChildren } from 'react'
import styled from 'styled-components'
export interface TextProps {
as?: string
children?: ReactChildren | React.ReactNode | string
}
export const Text = ({ as = 'p', children }: TextProps) => {
const Component = styled.p`
color: #000;
`
return <Component as={as}>{children}</Component>
}
Upvotes: 3
Views: 6799
Reputation: 8340
This one is kind of tricky. First of all, to type correctly Component
accepting as
prop you should give it correct typing for that as-component
. And the second problem is string
is wide enough to result in never
type for any other props of <Component as={as as string}>
. Including children
prop. So one has to narrow the type of as
for at least known html tags (as soon as you're allowing to pass only strings there and not custom react components).
So your code may be rewritten as:
import React, { ReactChildren } from 'react'
import styled from 'styled-components'
type KnownTags = keyof JSX.IntrinsicElements
export interface TextProps {
as?: KnownTags
children?: ReactChildren | React.ReactNode | string
}
export const Text = ({ as = 'p', children }: TextProps) => {
const Component = styled.p`
color: #000;
`
return <Component<typeof as> as={as}>{children}</Component>
}
Upvotes: 4