reach / reach-ui

The Accessible Foundation for React Apps and Design Systems
https://reacttraining.com/reach-ui/
MIT License
5.97k stars 559 forks source link

TypeScript Styling with Emotion #724

Closed janhesters closed 3 years ago

janhesters commented 3 years ago

🐛 Bug report

Note: This might not be a bug report. I also posted the question here on SO. I posted it here for the issues because in the docs for overriding styles it asks you to file a bug report when the documented example doesn't work.

Current Behavior

I'm using Next.js with TypeScript, Reach and Emotion. I want to style the menu-button components.

const MenuItem = styled(ReachMenuItem)``;

TypeScript complains:

with this TypeScript error. ``` error TS2769: No overload matches this call. Overload 1 of 6, '(component: ComponentClass & Pick & { as?: "symbol" | ... 176 more ... | undefined; } & { ...; }, any>, options?: StyledOptions<...> | undefined): CreateStyledComponent<...>', gave the following error. Argument of type 'ForwardRefExoticComponentWithAs<"div", Pick>' is not assignable to parameter of type 'ComponentClass & Pick & { as?: "symbol" | ... 176 more ... | undefined; } & { ...; }, any>'. Types of property 'propTypes' are incompatible. Type 'WeakValidationMap>> | undefined' is not assignable to type 'WeakValidationMap & Pick & { as?: "symbol" | ... 176 more ... | undefined; } & { ...; }> | undefined'. Type 'WeakValidationMap>>' is not assignable to type 'WeakValidationMap & Pick & { as?: "symbol" | ... 176 more ... | undefined; } & { ...; }>'. Types of property 'as' are incompatible. Type 'Validator<"div" | null | undefined> | undefined' is not assignable to type 'Validator<"symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 859 more ... | (FunctionComponent<...> & ComponentClass<...>)> | undefined'. Type 'Validator<"div" | null | undefined>' is not assignable to type 'Validator<"symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 859 more ... | (FunctionComponent<...> & ComponentClass<...>)>'. Type '"div" | null | undefined' is not assignable to type '"symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 859 more ... | (FunctionComponent<...> & ComponentClass<...>)'. Type 'undefined' is not assignable to type '"symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 859 more ... | (FunctionComponent<...> & ComponentClass<...>)'. Overload 2 of 6, '(component: ComponentType & Pick & { as?: "symbol" | ... 176 more ... | undefined; } & { ...; }>, options?: StyledOptions<...> | undefined): CreateStyledComponent<...>', gave the following error. Argument of type 'ForwardRefExoticComponentWithAs<"div", Pick>' is not assignable to parameter of type 'ComponentType & Pick & { as?: "symbol" | ... 176 more ... | undefined; } & { ...; }>'. Type 'ForwardRefExoticComponentWithAs<"div", Pick>' is not assignable to type 'FunctionComponent & Pick & { as?: "symbol" | ... 176 more ... | undefined; } & { ...; }>'. Types of property 'propTypes' are incompatible. Type 'WeakValidationMap>> | undefined' is not assignable to type 'WeakValidationMap & Pick & { as?: "symbol" | ... 176 more ... | undefined; } & { ...; }> | undefined'. Type 'WeakValidationMap>>' is not assignable to type 'WeakValidationMap & Pick & { as?: "symbol" | ... 176 more ... | undefined; } & { ...; }>'. Overload 3 of 6, '(tag: "symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 155 more ... | "view", options?: StyledOptions<...> | undefined): CreateStyledComponent<...>', gave the following error. Argument of type 'ForwardRefExoticComponentWithAs<"div", Pick>' is not assignable to parameter of type '"symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 155 more ... | "view"'. Type 'ForwardRefExoticComponentWithAs<"div", Pick>' is not assignable to type '"view"'. 50 const MenuItem = styled(ReachMenuItem)``; ```

Expected behavior

I can style the MenuButton and its components without type errors.

Reproducible example

CodeSandbox Template

Suggested solution(s)

The Reach team could document how to use TypeScript and Emotion with their library or make sure the typings work with the styled syntax.

Your environment

Software Name(s) Version
Reach Package @reach/menu-button 0.12.1
React 17.0.1
Browser any any
Assistive tech
Node 12.x
npm/yarn 1.2.2
Operating System MacOS
chaance commented 3 years ago

There seems to be some compatibility issues between how we type the as prop vs. how Emotion does it. Honestly not sure this is worth spending the time on right now, as our typing for as will likely (hopefully!) change soon anyway if this issue ever gets resolved. In the mean time, casting might be a good workaround: https://codesandbox.io/s/reach-bug-forked-ybj27?file=/src/App.tsx:162-176

chaance commented 3 years ago

Looks like this should be fixed in 0.15.0 https://codesandbox.io/s/reach-bug-forked-5t6hd