emotion version: 10.0.5react version: 16.6.3Relevant code:
// Custom styled function that is typed with my theme interface
import styled, { CreateStyled } from '@emotion/styled'
import { ITheme } from '../theme'
export default styled as CreateStyled<ITheme>
// Style function interface in a Util module
declare module 'Util' {
import { css } from '@emotion/core'
import { ITheme } from '../util/theme'
type CssType = typeof css
export interface IStyleFunction<P = {}> {
( arg0: { theme: ITheme } & P): ReturnType<CssType> | false | null
}
}
// Component code
type HeadingProps = {
size?: FontSizes
}
const baseStyles: IStyleFunction<HeadingProps> = ({ theme }) => css`
font-family: ${theme.fonts.heading};
`
const sizeStyles: IStyleFunction<HeadingProps> = ({
theme,
size = 'regular',
}) => {
const [defaultSize, smallBreakPoint] = fontSizes[size]
return css`
font-size: ${theme.fontSizes[defaultSize]};
${theme.mq[0]} {
font-size: ${theme.fontSizes[smallBreakPoint]};
}
`
}
const Heading = styled.h3<HeadingProps>(baseStyles, sizeStyles)
// Using the component
<Heading as="h5" size="tiny">
This is an important heading
</Heading>
What you did:
styled functionThemeProviderExtraProps to the styled functionas prop from Emotion 10 to change the element being used.What happened:
Typescript complains about the as prop not existing on the styled component

Reproduction:
I've created a code sandbox for this, but I don't think the setup there properly reflects mine. Since you can't seem to customize the tsconfig in the default Typescript + React starter, I don't know what else to do. In any case code sandbox does not show any typescript errors.
https://codesandbox.io/s/mzyzm524lj
Problem description:
I would like to not get compiler warnings about the as prop. If I add as to my component's ExtraProps (in the above example the HeadingProps), the compiler stops complaining.
Thanks a lot for the help. I love emotion and I've been using it for about a year now. Just new to the whole TypeScript thing. 😅
I cannot find a simple way that works with native DOM components and React components.
If you have a proper way to support as props, please feel free to send a PR!
Thanks for looking into this!
just hit the same problem myself :(
Same here 😄
Ran into this as well... Looks like withComponent works alright, so perhaps there is a way to use the logic there.
After tinkering with this myself and consulting other people - I don't think as can be strongly typed. I have to close this as non-actionable and we have to consider this a limitation of TS+emotion. Unless of course somebody figures it out and prepares a PR for this.
@Andarist what about as?: React.ElementType; ? Thats how it's typed in reflexbox typings.
See: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/reflexbox/index.d.ts#L24
I don't use emotion anymore, but if it does not have the as prop as an optional parameter it should be done for all emotion components.
The other issue (which is what I assume Andarist is referring to) that can't be solved now is getting TS to change the type signature based on what is specified in the as prop.
@Andarist would love to get this reopened and implement @slavikdenis's suggestion
This wouldn't be type-safe, but I guess we can just put it onto type system not being flexible enough to support this dynamic pattern. cc @JakeGinnivan thoughts on enabling this simplistic type for as prop?
The as prop should have a type so it can be used. I just don't think we want to go near the changing prop types based on the type of as. as?: React.ElementType; seems reasonable. Even as?: React.ElementType | keyof JSX.IntrinsicElements
Has this been resolved in the upcoming v11? Otherwise, I'd like to take a stab at it — any pointers to relevant files would be appreciated :)
I don't think it has been done.
In packages/styled-base/types/index.d.ts, add the as prop to StyledComponent. I think as?: React.ElementType | keyof JSX.IntrinsicElements should be enough as mentioned above.
Then in packages/styled-base/types/tests.tsx, write a component which consumes the prop to just make sure it all works as expected.
Thanks for the hints @JakeGinnivan! Much appreciated.
Unfortunately, the types have changed quite a bit in the next branch for v11. I've tried to make the changes there and while the test works, I'm not sure whether it's the correct approach. Here's the draft PR: #1874.
Would you consider this a breaking change? Should I backport this to v10?
I'm facing the same issue, the way I'm fixing it for now is just adding a as?: React.ElementType | keyof JSX.IntrinsicElements directly in my components.
Any update whether or not this is going to be natively supported?
There’s a pending PR (#1874) to add it for Emotion 11. I’d be happy to backport it to 10 as well.
Using emotion v10 as well, the type suggested above seems to work for me locally:
import React from 'react';
import { Link } from 'react-router-dom';
import styled from '@emotion/styled';
interface StyledLinkProps {
as?: React.ElementType;
}
const StyledLink = styled.a<StyledLinkProps>`
/* ... */
`;
const Nav = () => (
<StyledLink as={(props) => <Link {...props} to="/somewhere" />}>
Go somewhere
</StyledLink>
);
Just merged this into next branch so it will be available in the next v11 release. There are no plans to backport this change to v10 though. Hope you understand.
Most helpful comment
@Andarist what about
as?: React.ElementType;? Thats how it's typed in reflexbox typings.See: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/reflexbox/index.d.ts#L24