🇺🇦 STOP WAR IN UKRAINE 🇺🇦

Emotion is built with Flow, so it exports type definitions for most of its packages, including @emotion/styled.

@emotion/styled

The styled package can be used to define styled components in two ways, by calling styled(), or by using the styled.* shortcuts.

Unfortunately, Flow doesn’t currently support generic types on tagged templates, this means if you’d like to explictly type a styled component props, you will have to use one of the following alternatives:

import styled from '@emotion/styled'

// Option A
const A = styled<Props>('div')`
  color: red;
`

// Option B
const B = styled.div<Props>({
  color: 'red',
})

Styled components are annotated the same way normal React components are:

import styled from '@emotion/styled'

type Props = { a: string }
const Link = styled<Props>('a')`
  color: red;
`

const App = () => <Link href="#">Click me</Link>

Just like for normal React components, you don’t need to provide type annotations for your styled components if you don’t plan to export them from your module:

import styled from '@emotion/styled'

const Internal = styled.div`
  color: red;
`

Be aware, Flow infers the return type of your components by referencing their return type, this means you will need to annotate the properties of the root component in the case below:


const Container = styled.div`
                  ^^^^^^^^^^^ Missing type annotation for P. P is a type parameter declared in function type [1] and was implicitly instantiated at
encaps tag [2].   
  color: red;
`

export const App = () => <Container />

You can use React$ElementConfig to obtain the props type of a HTML tag, or of any existing React component:

import type { ElementConfig } from 'react'

type Props = ElementConfig<'div'>
const Container = styled<Props>('div')`
  color: red;
`

export const App = () => <Container />
import type { ElementConfig } from 'react'
import styled from '@emotion/styled'

const Container = styled<ElementConfig<'div'>>('div')`
  background-color: yellow;
`

const App = () => (
    <Container>{() => 10}</Container>
               ^^^^^^^^^^ Cannot create Container element because in property children:
                          • Either inexact function [1] is incompatible with exact React.Element [2].
                          • Or function [1] is incompatible with React.Portal [3].
                          • Or property @@iterator is missing in function [1] but exists in $Iterable [4].
)

Alternatively, you can define the return type of your component, so that Flow doesn’t need to infer it reading the props type of the internal component:

import type { Node } from 'react'

const Container = styled.div`
  color: red;
`

export const App = (): Node => <Container />