Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Component selectors don't work with TypeScript CreateStyled<Theme> #1320

Closed
johnjensenish opened this issue Apr 17, 2019 · 16 comments
Closed

Comments

@johnjensenish
Copy link

  • emotion version: 10.0.10
  • react version: 16.8.6

Relevant code:

styled.ts:

import styled, { CreateStyled } from '@emotion/styled'
import { Theme } from './theme'

export default styled as CreateStyled<Theme>

text.tsx:

import styled from 'src/styles/styled'

// ...

export const Title2 = styled<'h3', TextProps>('h3')`
  color: ${props => props.theme.colors.charcoalGrey};
  ${typography.title2}
  ${textStyles}
`

export const SectionTitle = styled<'h4', TextProps>('h4')`
  color: ${props => props.theme.colors.charcoalGrey};
  ${typography.sectionTitle}
  ${textStyles}
`

someOtherFile.tsx:

const DeduplicateExaggeratedMargins = styled(Box)`
  ${Title2} + ${SectionTitle} {
    margin-top: ${props => props.theme.space[standardMargin]}px;
  }
`

What you did:

  1. I followed the instructions here to define a theme with our own version of styled.
  2. Now I can't use Component Selectors!

What happened:

I received an error:

Error: Component selectors can only be used in conjunction with babel-plugin-emotion.

Reproduction:

Problem description:

Switching to test.tsx to use import styled from '@emotion/styled' rather than our version of styled with theming.

Suggested solution:

Make babel-plugin-emotion support what is documented in the "Typescript.md" file.

@johnjensenish
Copy link
Author

Related to #1203?

@macalinao
Copy link
Contributor

I have the same problem! Probably #1203.

@kristofdombi
Copy link

kristofdombi commented May 14, 2019

I ran into the same issue as well.
This is related to #1220, I suppose! 🤔

@mario-jerkovic
Copy link

I have the same problem... I switched to import styled from "@emotion/styled" but its really pain in the a** to be without typed theme property. Did maybe some managed to do some workaround for injecting theme interface...

@IvanRodriCalleja
Copy link

IvanRodriCalleja commented Aug 20, 2019

I had the same problem with CreateStyled<Theme> and i fixed it in a simple way (i think) taking the problem into the typings that is where the problem comes.

I "overrode" the existing typings from @emotion/styled because it is the problem of our not typed theme in styled-components.

customTypings.d.ts

image

Whit this, you can use the @emotion/styled (this is the alias that you need to use because macros search this alias from babel-preset-emotion and if you use other it will no parse anything)

I am doing the same that you have to do to create a "custom theme" into typings, with this i avoid to play gith alias in webpack and declare this modules in typings (it creates problems with HMR).

When you use your styled now you have a typed theme.

anyComponent.tsx

image

There is only one case in which this solution doesn't work, it is if you need to have more than one different theme in the same project (to be honest i don't think anybody need this)

@OzzieOrca
Copy link

So no one else has to retype the above code, I added types/@emotion/styled.d.tscontaining:

import { CreateStyled } from '@emotion/styled/types/index';

import { MyTheme } from '../../src/myTheme';
export * from '@emotion/styled/types/index';
const customStyled: CreateStyled<MyTheme>;
export default customStyled;

@IvanRodriCalleja
Copy link

Where did you exactly added it?

@mheisig
Copy link

mheisig commented Sep 23, 2019

I tried the module declaration approach above but I get Typescript errors any time I try to reference the theme:

padding: ${p => p.theme.space.x3};

throws this:
Property 'space' does not exist on type 'object'

@IvanRodriCalleja
Copy link

Could you provide the module declaration?

Is the type of the theme in the line padding: ${p => p.theme.space.x3}; the same as you defined in the module or it says that is Object?

@mheisig
Copy link

mheisig commented Sep 23, 2019

@IvanRodriCalleja The module declaration looks like this:

declare module '@emotion/styled' {
  import { CreateStyled } from '@emotion/styled/types/index'
  import { Theme } from '../types/interfaces'

  export * from '@emotion/styled/types/index'
  const customStyled: CreateStyled<Theme>
  export default customStyled
}

A truncated version of the Theme definition:

export interface Theme {
  space: {
    xxxs: string
    xxs: string
    xs: string
    s: string
    m: string
    x1: string
    x2: string
    x3: string
}

@mheisig
Copy link

mheisig commented Sep 23, 2019

I've got simplified example here that works fine: https://codesandbox.io/s/emotion-issue-template-bqs1k

I'm not sure what's different in my setup that's causing it to not work.

@IvanRodriCalleja
Copy link

Move your global.d.ts at the same folder that package.json, i did that and it worked.

@mheisig
Copy link

mheisig commented Sep 24, 2019

@IvanRodriCalleja That actually worked! Thanks!

@tpict
Copy link

tpict commented Oct 14, 2019

Sorry to use this issue for general TS support, but I'm really struggling with this issue. I've tried both the types/@emotion/styled.d.ts and module declaration approaches; the former doesn't seem to do anything, and I'm having an issue with the latter in that it doesn't seem to be importing my theme type correctly–in my styled components, theme is typed as object if I do this:

declare module "@emotion/styled" {
  import { CreateStyled } from "@emotion/styled/types/index";
  import { Theme } from "./src/theme/types";

  export * from "@emotion/styled/types/index";
  const customStyled: CreateStyled<Theme>;
  export default customStyled;
}

but if I declare Theme inline, it is typed as expected. I don't really want to have to move my Theme type and all its dependencies here though... any hints?

edit: I got around this issue by importing Theme using import: import("./src/theme/types").Theme

@belgattitude
Copy link

@tpict Are you using Nextjs by chance ?

To get around, I've just created an alias in both tsconfig.json and babelrc. i.e:

In tsconfig.json

  "compilerOptions": {
    "paths": {
      "@src/*": [
        "src/*"
      ]
    }

.babelrc

  "plugins": [
    ["emotion", { "sourceMap": true }],
    ["module-resolver", {
      "root": ["."],
      "alias": {
        "@src": "./src"
      }
    }]
  ]

Then changed the import to import {Theme} from "@src/themes/theme.type";.

In my case it's specific nextjs and frankly I didn't to spend too much time, just noticed the path/module resolution was not good and made an alias. But I think this can work in other scenarios as well.

@Andarist
Copy link
Member

This will be addressed with #1220

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants