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

[styled-component] Support css prop #31245

Open
4 tasks done
sarod opened this issue Dec 10, 2018 · 52 comments
Open
4 tasks done

[styled-component] Support css prop #31245

sarod opened this issue Dec 10, 2018 · 52 comments

Comments

@sarod
Copy link

sarod commented Dec 10, 2018

  • I tried using the @types/styled-component package and had problems.
  • I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).
  • Mention the authors (see Definitions by: in index.d.ts) so they can respond.

I tried using the new css prop (https://medium.com/styled-components/announcing-native-support-for-the-css-prop-in-styled-components-245ca5252feb) with the babel typescript presets and the styled-component babel-plugin.

This runs fine but type-checking fails because type definition does not extend builtin components (div, button...) with the 'css' prop.

Note that a similar prop seems to be supported in emotionjs type definitions by globally extending the react module:

declare module 'react' {
  interface DOMAttributes<T> {
    css?: InterpolationWithTheme<any>
  }
}

See
https://github.com/emotion-js/emotion/blob/1b7333a837813949fa4fe301bb0d53887e784b8b/packages/core/types/index.d.ts#L83

@Jessidhia
Copy link
Member

Jessidhia commented Dec 10, 2018

It is supported but opt-in.

import {} from 'styled-components/cssprop' in a TypeScript file and it will be made available. You only need to import this once in the project.

The {} from is important to tell TypeScript it's OK to remove the import from the code -- we just want the types. If that import remains you'll get an error.

@Jessidhia
Copy link
Member

Jessidhia commented Dec 10, 2018

I need to find some time to get on with updating the docs... moving the types to DT had advantages, especially with testing tooling, but the docs are now completely independent

@sarod
Copy link
Author

sarod commented Dec 11, 2018

Great thanks a lot for the info

@sabonis
Copy link

sabonis commented Dec 14, 2018

There might have some issues when use with babel-typescript.
babel/babel#8361

@ralexand56
Copy link

ralexand56 commented Dec 19, 2018

It is supported but opt-in.

import {} from 'styled-components/cssprop' in a TypeScript file and it will be made available. You only need to import this once in the project.

The {} from is important to tell TypeScript it's OK to remove the import from the code -- we just want the types. If that import remains you'll get an error.

Wow! This took forever for me to find. Is there anywhere convenient for this to be documented. Why is it opt-in?

Actually it still doesn't work. I get the following error:

Module not found: Can't resolve 'styled-components/cssprop' in 'C:\github\reduxtut\src'

@benvp
Copy link

benvp commented Dec 22, 2018

It is supported but opt-in.

import {} from 'styled-components/cssprop' in a TypeScript file and it will be made available. You only need to import this once in the project.

The {} from is important to tell TypeScript it's OK to remove the import from the code -- we just want the types. If that import remains you'll get an error.

Tried this, but this does not seem to work for me. Still getting the same type checking error. It does show up in the properties but I get this typechecking error:

Type '{ css: string; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.
  Property 'css' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'

@Jessidhia
Copy link
Member

Jessidhia commented Dec 25, 2018

Don't omit the {} from in import {} from, it's there to get TypeScript to completely delete the import before your bundler sees it.

Alternatively, use /// <reference types="styled-components/cssprop" />. Where you also need the 3 slashes, don't be cheap.


Also, strange that TypeScript is not seeing the css. I wonder if it's something that only works on 3.2? But if that was the case, tests wouldn't be passing, but they pass and all that they do is import {} from 'styled-components/cssprop'.

@benvp
Copy link

benvp commented Dec 26, 2018

It's a bit strange, maybe my project configuration is incorrect at some point, but when I add the exact same file cssprop.d.ts to my project root, everything works. oO

@lski
Copy link

lski commented Feb 14, 2019

There might have some issues when use with babel-typescript.
babel/babel#8361

To add to this comment, I have also been having this issue with babel-typescript.

I am using VSCode and using the empty import, that stops VSCode complaining (probably due to it running tsc directly).

But when compiling the code using webpack (4.29.2) babel (core 7.1.6 env 7.3.1 ts 7.1.0) and typescript (3.3.1) along with the fork-ts-checker-webpack-plugin (0.5.2) it throws an error saying it Can't resolve 'styled-components/cssprop'.

Update: Ive tried changing import {} from 'styled-components/cssprop' to import * as types from 'styled-components/cssprop' and that works. As the file is just a type (d.ts) file webpack simply ignores it and doesnt include it in the bundle.

Additionally, the reference tag does work as well, but looks ugly 😂

@fabb
Copy link

fabb commented Mar 19, 2019

The import {} works, but when using a template function in the template string which accesses the theme, typescript complains that the props parameter implicitly has any type:

<div css={`color: ${props => props.theme.c.primary};`}/>

In regular styled components (e.g. style.div``), the typings work fine. Any ideas how to resolve this?

@fabb
Copy link

fabb commented Mar 21, 2019

ah ok, just use "css``":

<div css={css`color: ${props => props.theme.c.primary};`}/>

@sami616
Copy link

sami616 commented Apr 18, 2019

None of the above worked for me, however extending Reacts DOMAttributes interface via a namespace in my own declaration file seemed to do the job.

/// <reference path="node_modules/@types/react/index.d.ts"/>

// Add support for css prop
declare namespace React {
  interface DOMAttributes<T> {
    css?: any
  }
}

@peduarte
Copy link
Contributor

peduarte commented May 26, 2019

Having similar issue over here 👋

Is there gonna be support for this?

@njdancer
Copy link

njdancer commented May 28, 2019

Actually it still doesn't work. I get the following error:

Module not found: Can't resolve 'styled-components/cssprop' in 'C:\github\reduxtut\src'

I was having the same issue and it took me a day of on and off searching to find this buried deep.
import * as types from 'styled-components/cssprop'

Copying here as google seems to like this thread.

@paolostyle
Copy link
Contributor

paolostyle commented May 29, 2019

I simply created a file in src/typings called cssprop.d.ts:

import { CSSProp } from 'styled-components';

declare module 'react' {
  interface Attributes {
    css?: CSSProp;
  }
}

and it seems to work fine.

@ralexand56
Copy link

ralexand56 commented May 29, 2019

Why aren't the type definitions being updated to support this?

@nhooyr
Copy link

nhooyr commented Jul 16, 2019

Yea, why is it opt in?

@nhooyr
Copy link

nhooyr commented Jul 16, 2019

Ah, it's described in index.d.ts:

/**
 * The CSS prop is not declared by default in the types as it would cause 'css' to be present
 * on the types of anything that uses styled-components indirectly, even if they do not use the
 * babel plugin.
 *
 * You can load a default declaration by using writing this special import from
 * a typescript file. This module does not exist in reality, which is why the {} is important:
 *
 * ```ts
 * import {} from 'styled-components/cssprop'
 * ```
 *
 * Or you can declare your own module augmentation, which allows you to specify the type of Theme:
 *
 * ```ts
 * import { CSSProp } from 'styled-components'
 *
 * interface MyTheme {}
 *
 * declare module 'react' {
 *   interface Attributes {
 *     css?: CSSProp<MyTheme>
 *   }
 * }
 * ```
 */

@insidewhy
Copy link

insidewhy commented Jul 28, 2019

As @njdancer points out, import {} from 'styled-components/cssprop' just doesn't work. Had to use import * as _ from 'styled-components/cssprop' here. TypeScript 3.5.3.

@nhooyr
Copy link

nhooyr commented Nov 10, 2019

This is really confusing behaviour. Can we change it to be included by default? @Jessidhia

@likern
Copy link

likern commented Dec 1, 2019

I've tested several provided solutions for Typescript 3.7.2 and React Native 0.61.

import {} from 'styled-components/cssprop' helps Typescript (passes Typescript checks), but fails when metro bundler tries to bundle dependencies into application

error: bundling failed: Error: Unable to resolve module styled-components/cssprop from index.js: styled-components/cssprop could not be found within the project

/// <reference types="styled-components/cssprop" /> perfectly works and application is run without errors.

So my final solution was to put /// <reference types="styled-components/cssprop" /> into index.js file:

/// <reference types="styled-components/cssprop" />
import {AppRegistry} from 'react-native';
import App from './src/App';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);

@doronnac
Copy link
Contributor

doronnac commented Jan 9, 2020

For some reason all of the solutions above break material-ui's Typography component, specifically the component prop.
<Typography component="h1">Throws an error when applying any of the css prop fixes</Typography>
Error is:
Type 'string' is not assignable to type 'ElementType<HTMLAttributes<HTMLElement>>'

Edit: My bad I guess. Kept types in a folder called @types and typescript didn't like it for some reason

@jpaas
Copy link

jpaas commented Feb 13, 2020

I'm using react native 0.61.5 with styled-components 5.01 and the css prop works properly, but tsc always gives me this error on the prop. I have tried every suggestion in this issue.

  Overload 1 of 2, '(props: Readonly<TextProps>): Text', gave the following error.
    Type 'FlattenInterpolation<ThemeProps<Theme>>' is not assignable to type 'InterpolationWithTheme<any>'.
      Type 'FlattenInterpolation<ThemeProps<Theme>>' is not assignable to type 'ObjectInterpolation<undefined>'.
        Types of property 'filter' are incompatible.
          Type '{ <S extends Interpolation<ThemeProps<Theme>>>(callbackfn: (value: Interpolation<ThemeProps<Theme>>, index: number, array: readonly Interpolation<ThemeProps<Theme>>[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: Interpolation<...>, index: number, array: readonly Interpolation<...>[]) => unknown, thisArg...' is not assignable to type 'string | string[] | undefined'.
            Type '{ <S extends Interpolation<ThemeProps<Theme>>>(callbackfn: (value: Interpolation<ThemeProps<Theme>>, index: number, array: readonly Interpolation<ThemeProps<Theme>>[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: Interpolation<...>, index: number, array: readonly Interpolation<...>[]) => unknown, thisArg...' is missing the following properties from type 'string[]': pop, push, concat, join, and 27 more.
  Overload 2 of 2, '(props: TextProps, context?: any): Text', gave the following error.
    Type 'FlattenInterpolation<ThemeProps<Theme>>' is not assignable to type 'InterpolationWithTheme<any>'.
      Type 'FlattenInterpolation<ThemeProps<Theme>>' is not assignable to type 'ObjectInterpolation<undefined>'.

47     <Text css={textStyle} {...textProps}>

@likern
Copy link

likern commented Feb 13, 2020

I'm using react native 0.61.5 with styled-components 5.01 and the css prop works properly, but tsc always gives me this error on the prop. I have tried every suggestion in this issue.

  Overload 1 of 2, '(props: Readonly<TextProps>): Text', gave the following error.
    Type 'FlattenInterpolation<ThemeProps<Theme>>' is not assignable to type 'InterpolationWithTheme<any>'.
      Type 'FlattenInterpolation<ThemeProps<Theme>>' is not assignable to type 'ObjectInterpolation<undefined>'.
        Types of property 'filter' are incompatible.
          Type '{ <S extends Interpolation<ThemeProps<Theme>>>(callbackfn: (value: Interpolation<ThemeProps<Theme>>, index: number, array: readonly Interpolation<ThemeProps<Theme>>[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: Interpolation<...>, index: number, array: readonly Interpolation<...>[]) => unknown, thisArg...' is not assignable to type 'string | string[] | undefined'.
            Type '{ <S extends Interpolation<ThemeProps<Theme>>>(callbackfn: (value: Interpolation<ThemeProps<Theme>>, index: number, array: readonly Interpolation<ThemeProps<Theme>>[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: Interpolation<...>, index: number, array: readonly Interpolation<...>[]) => unknown, thisArg...' is missing the following properties from type 'string[]': pop, push, concat, join, and 27 more.
  Overload 2 of 2, '(props: TextProps, context?: any): Text', gave the following error.
    Type 'FlattenInterpolation<ThemeProps<Theme>>' is not assignable to type 'InterpolationWithTheme<any>'.
      Type 'FlattenInterpolation<ThemeProps<Theme>>' is not assignable to type 'ObjectInterpolation<undefined>'.

47     <Text css={textStyle} {...textProps}>

Try to add /// <reference types="styled-components/cssprop" /> into index.js file. This should help. I'm using css property with Typescript without problems.

@jpaas
Copy link

jpaas commented Feb 14, 2020

The triple slash didn't work but this did...

global.d.ts

import { CSSProp } from "styled-components" // eslint-disable-line @typescript-eslint/no-unused-vars

declare global {
  namespace JSX {
    interface IntrinsicAttributes {
      css?: CSSProp
    }
  }
}

@marsonmao
Copy link

marsonmao commented Aug 31, 2020

I added the cssprop definition, but my css prop on div still shows error. Anyone knows how to fix it?

The error message is "Type 'FlattenSimpleInterpolation[]' is not assignable to type ... ".


Details:

I'm using it as an ARRAY like this

      <div css={[flex.row, flex.crossAlignCenter]}>

The flex object is like this

const flex = {
  row: css`
    display: flex;
    flex-direction: row;
  `,
  crossAlignCenter: css`
    align-items: center;
  `,
};

Then the error says

Type 'FlattenSimpleInterpolation[]' is not assignable to type ... (MANY KINDS of definitions, like 33 of them)

I guess the problem is that css prop does not accept FlattenSimpleInterpolation[]?

@karol-majewski
Copy link
Contributor

karol-majewski commented Sep 30, 2020

This didn't work for me:

import {} from 'styled-components/cssprop';

I kept receiving the following error.

Module not found: Error: Can't resolve 'styled-components/cssprop' 

This notation from TypeScript 3.8 worked:

import type {} from 'styled-components/cssprop';

@peduarte
Copy link
Contributor

peduarte commented Oct 1, 2020

I've just given up completely now 🤷 This issue is from 2018 😅

Switched to using Stitches

@giuband
Copy link
Contributor

giuband commented Nov 3, 2020

For the record the import {} from 'styled-components/cssprop' solution eventually caused a serious issue a large project where TS could not validate styled components anymore (styled components were being inferred as any).
I solved this issue by manually creating a new cssprop.d.ts file with the following content:

import { CSSProp } from 'styled-components'

declare global {
  namespace JSX {
    interface IntrinsicAttributes {
      css?: CSSProp
    }
  }
}

Now the css prop is working and typescript is still validating correctly all styled components

@hector-del-rio
Copy link

hector-del-rio commented Nov 27, 2020

Adding the following in any declaration file in the project seems to work as well, e.g: styled-components.d.ts:

import 'styled-components/cssprop';

@rodrigojmr
Copy link

rodrigojmr commented Dec 8, 2020

I've set it up according to @giuband so I don't get any error and the type of css prop is recognized, but the style isn't applied.

image

@creativiii
Copy link

creativiii commented Dec 9, 2020

None of the solutions above worked. Or some worked but then the error appeared again if I added a new file with the CSS prop.

Seriously, how is this still a problem?

@abheist
Copy link

abheist commented Jan 7, 2021

This worked for me

import type {} from 'styled-components/cssprop';

🙏

@qdozaq
Copy link

qdozaq commented Jan 13, 2021

Heads up, something I ran into, if you have storybook in your repo it uses emotion which has it's own type declaration for the css prop

//from /node_modules/@emotion/core/types
declare module 'react' {
  interface DOMAttributes<T> {
    css?: InterpolationWithTheme<any>
  }
}

declare global {
  namespace JSX {
    /**
     * Do we need to modify `LibraryManagedAttributes` too,
     * to make `className` props optional when `css` props is specified?
     */

    interface IntrinsicAttributes {
      css?: InterpolationWithTheme<any>
    }
  }
}

BOTH of these need to be overwritten when declaring the css prop definition for styled-components

What I used:

import { CSSProp } from 'styled-components';
declare module 'react' {
  interface DOMAttributes<T> {
    css?: CSSProp;
  }
}
declare global {
  namespace JSX {
    interface IntrinsicAttributes {
      css?: CSSProp;
    }
  }
}

@mulholo
Copy link
Contributor

mulholo commented Feb 16, 2021

Thanks for pointing out the emotion/storybook issue. Using that, along with import 'styled-components/cssprop'; fixed things in my project.

In other words, the solution was to have the following in a styled-components.d.ts

import { CSSProp } from 'styled-components';
import 'styled-components/cssprop';

declare module 'react' {
  interface DOMAttributes<T> {
    css?: CSSProp;
  }
}
declare global {
  namespace JSX {
    interface IntrinsicAttributes {
      css?: CSSProp;
    }
  }
}

@silvenon

This comment has been minimized.

@silvenon

This comment has been minimized.

@silvenon
Copy link

silvenon commented Mar 1, 2021

Sorry for hasty comments above, I finally sat down and posted a question on Stack Overflow explaining how I failed to get the css prop working once I brought Storybook into the equation, in case anyone wants to take a stab at it. ❤️

I tried the solutions above, but in my case the css prop type definition didn't override the one from @emotion/core (used by Storybook), it clashed. 😕 Here's the minimal repro, the branch is ts/styled-components-storybook.

@httpete
Copy link

httpete commented Mar 26, 2021

Sorry for hasty comments above, I finally sat down and posted a question on Stack Overflow explaining how I failed to get the css prop working once I brought Storybook into the equation, in case anyone wants to take a stab at it. ❤️

I tried the solutions above, but in my case the css prop type definition didn't override the one from @emotion/core (used by Storybook), it clashed. 😕 Here's the minimal repro, the branch is ts/styled-components-storybook.

Have exact same thing here. I am hoping to learn how to override or specify typing more broadly.

@uoon-dev
Copy link

uoon-dev commented Apr 1, 2021

Sorry for hasty comments above, I finally sat down and posted a question on Stack Overflow explaining how I failed to get the css prop working once I brought Storybook into the equation, in case anyone wants to take a stab at it. ❤️

I tried the solutions above, but in my case the css prop type definition didn't override the one from @emotion/core (used by Storybook), it clashed. 😕 Here's the minimal repro, the branch is ts/styled-components-storybook.

Is there any update?

@nelsondude
Copy link

nelsondude commented Apr 15, 2021

Same as #31245 (comment)

I'm also having this issue with storybook specifically. Since emotion is a dependency, the typings there arent being overridden when i include

import { CSSProp } from 'styled-components';
import 'styled-components/cssprop';

declare module 'react' {
  interface DOMAttributes<T> {
    css?: CSSProp;
  }
}
declare global {
  namespace JSX {
    interface IntrinsicAttributes {
      css?: CSSProp;
    }
  }
}

in a styled-components.d.ts file.

However, if i go to the type definitions in node_modules and comment out the typings, then these custom typings work correctly. Is there a way I can specify that these custom typings should override the ones in node_modules?

@thomasmery
Copy link

thomasmery commented Apr 20, 2021

ran into this as well and somehow I'm wondering how this is not come up more, using styled-components with a TS project and storybook seems to be pretty common

so it makes me wonder if there is an 'obvious' fix, or something I (we) did not do correctly.

has anyone in this thread been able to solve this? I read @silvenon SO post, did you fix this?

thanks

@silvenon
Copy link

silvenon commented Apr 20, 2021

did you fix this?

Unfortunately no 😞 My question was too complicated for Stack Overflow anyway, the reason why I wasn't able to fix this was because I lack some deeper knowledge of TypeScript, so I'm sure I'll be able to eventually narrow down my question to not be about the css prop at all, I just haven't come around to it yet.

@thomasmery
Copy link

thomasmery commented Apr 20, 2021

Thanks,

I'll update here if I can find a way

@thomasmery
Copy link

thomasmery commented Apr 21, 2021

FWIW and as a follow up to the comments related to: storybook V6, emotion/core

like described here #31245 (comment) and #31245 (comment)

I, also, seemingly, have fixed the conflict between the styled-components & emotion cssprop type definitions by, as was suggested above, having an ambient *.d.ts file containing

import { CSSProp } from 'styled-components';

declare module 'react' {
  interface DOMAttributes<T> {
    css?: CSSProp;
  }
}

declare global {
  namespace JSX {
    interface IntrinsicAttributes {
      css?: CSSProp;
    }
  }
}

I previously, b4 storybook introduction to the project, had the /// directive and that was working fine

I removed it in favour of the whole declaration override above
I also tried to keep it and just have the 'namespace JSX' declaration but it does not work and I think this might be because the declaration in st styled-components/cssprop def file extends 'Attributes' and not 'DOMAttribute' (maybe)

hope this helps

@as-zlynn-philipps
Copy link
Contributor

as-zlynn-philipps commented Aug 31, 2021

How is there not a solution to this yet? None of the above snippets work for me, VS Code is insistent on latching onto Emotion's type declaration for the css prop.

@jrapala
Copy link

jrapala commented Mar 4, 2022

Seems like emotion-js has fixed this issue in v11: emotion-js/emotion#1800

Until then, I've added a .yarnclean file with the following to ignore all of the conflicting types:

@emotion/*/types

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