How can JSDoc be used to type props of styled-components in combination with tsconfig.json and tsc
.
In TypeScript this is very easy with a simple generic, unfortunately I cannot achieve the same using JSDoc. I would imagine doing something like this.
/** @type {import('styled-components').styled["div"]<{ $open: boolean }>} */
const ChildContent = styled.div`
animation: ${p => p.$open ? slideOpen : slideClose};
`
I noticed that StyleFunction works and the props can be provided using the generic. However, this type does not include any information about the component, only the props of the component. So the code below does not show any errors, until it's used with for instance a ref property.
/** @type {import("styled-components").StyleFunction<{ $open: boolean }>} */
const ChildContent = styled.div`
animation: ${p => p.$open ? slideOpen : slideClose};
`
// breaks here, 'ChildContent' cannot be used as a JSX component.
const Component = <ChildContent style={{ position: "absolute" }} $open={show} />
So another possible solution would be to combine this with another generic that takes the Runtime
and Target
. But, even better would be to directly access the function generic in Styled (exported as StyledInstance).
Big thanks for anyone who can help find the correct type.
Thanks to Jesus Jemenez Cordero I better understood the StyledInstance type. And with some type inference it is possible to create a simple type and add that to a .d.ts file.
Here are the steps I took to get to the solution: (Step 4 and 5 contain the final code)
/**
* @typedef {import('styled-components').StyledInstance<"web", "div", { $open: boolean }, {}>} DivComponent
*/
const ChildContent = /** @type {DivComponent} */ (styled.div)`
animation: ${p => p.$open ? slideOpen : slideClose};
`
/**
* @typedef {import('styled-components').StyledInstance<"web", "div", { $open: boolean } & import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>} DivComponent
*/
Target
, HTML OuterProps
and OuterStatics
are already filled in. So create a .d.ts file with that can extract these automatically.type GetComponent<Target extends import("styled-components").WebTarget> = import("styled-components").Styled[Target]
type GetComponentHtmlProps<Component> = Component extends import("styled-components").StyledInstance<"web", any, infer X, any> ? X : any
type StyledComponent<Target extends import("styled-components").WebTarget, Props extends object> = import("styled-components").StyledInstance<
"web", Target,
Props & GetComponentHtmlProps<GetComponent<Target>>,
{}
>
StyledComponent
type to add props to the type./**
* @typedef {StyledComponent<"div", { $open: boolean }>} DivComponent
*/
const ChildContent = /** @type {DivComponent2} */ (styled.div)`
animation: ${p => p.$open ? slideOpen : slideClose};
`
{
"files": [
"./types.d.ts"
]
}
Unfortunately this is an incomplete answer. The answer at least misses extending existing styled-components using the styled(MyComponent)
syntax.