Type 'string' is not assignable to type '"inherit" | "initial" | "unset" | "fixed" | "absolute" | "static" | "relative" | "sticky"'
ReactjsTypescriptWebpackReactjs Problem Overview
I get the following error in my application (npm 5.4.2, react 15.4, typescript 2.5.3, webpack 2.2.1, webpack-dev-server 2.4.1).
This will work:
<div style={{position: 'absolute'}}>working</div>
This will not compile:
const mystyle = {
position: 'absolute'
}
<div style={mystyle}>not working</div>
The compile error is:
ERROR in ./src/components/Resource.tsx
(61,18): error TS2322: Type '{ style: { position: string; }; children: string; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.
Type '{ style: { position: string; }; children: string; }' is not assignable to type 'HTMLAttributes<HTMLDivElement>'.
Types of property 'style' are incompatible.
Type '{ position: string; }' is not assignable to type 'CSSProperties'.
Types of property 'position' are incompatible.
Type 'string' is not assignable to type '"inherit" | "initial" | "unset" | "fixed" | "absolute" | "static" | "relative" | "sticky"'.
webpack: Failed to compile.
But what't the difference? I can fix it with:
const mystyle = {
position: 'absolute' as 'absolute'
}
but is this a good solution?
I don't have this problem with other style/css properties.
I found a similar problem on github: https://github.com/Microsoft/TypeScript/issues/11465 but if understand it right, it was a typescript bug in an ealier version.
Any help appreciated.
Reactjs Solutions
Solution 1 - Reactjs
This is a workaround, but it is alright. Some other solution is:
const mystyles = {
position: 'absolute',
} as React.CSSProperties;
You can check back when this issue will be solved. Around TS 2.6 i guess, judging by milestones.
Solution 2 - Reactjs
Use the React.CSSProperties type:
import React, { CSSProperties } from "react";
const myStyles: CSSProperties = {
position: 'absolute',
}
Then just use the style as normal:
<div style={myStyles} />
Solution 3 - Reactjs
The answer by superluminary doesn't work if you have nested style objects. In this case you can create a type:
import React, { CSSProperties } from 'react';
export interface StylesDictionary{
[Key: string]: CSSProperties;
}
And use it like so:
const styles:StylesDictionary = {
someStyle:{
display:'flex',
justifyContent:'center',
},
someOtherStyle:{
display:'flex',
justifyContent:'center',
alignItems:'center',
}
}
And then:
<div style={styles.someStyle} />
Solution 4 - Reactjs
You can make TypeScript infer literal values on the entire object by using a const assertion:
const mystyle = {
position: 'absolute'
} as const;
This way, if you add more properties to mystyle
, it will work for them as well.
Solution 5 - Reactjs
I had a similar issue trying to pass down a wrapperHeight string value (100px, 10vw, 100vh etc) to a HeroImage component. The solution was to actually use string literals around the value inside the CSS object (mouthful):
interface HeroImageProps {
src: StaticImageData,
alt: string,
wrapperHeight: string,
}
export default function HeroImage({ src, alt, wrapperHeight }: HeroImageProps) {
const wrapperStyles: React.CSSProperties = {
height: `${wrapperHeight}`
}
return (
<div className={styles.heroImage} style={wrapperStyles} >
<Image
src={src}
alt={alt}
layout="fill"
priority
/>
</div>
)
}