emotion version: 10.0.6react version: 16.6.3Relevant code:
const Test = styled("div")(() => {
const attributes = {
textAlign: "center",
};
return {
...attributes,
};
});
What you did:
tried to assign textAlign to a styled component. This is unique to textAlign. Also if I set textAlign directly (not using the spread operator) everything works just fine:
const Test = styled("div")(() => {
return {
textAlign: "center",
};
});
What happened:
I receive a TypeScript compile error (not only linting):
Type error: Argument of type '() => { textAlign: string; }' is not assignable to parameter of type 'TemplateStringsArray'.
Type '() => { textAlign: string; }' is missing the following properties from type 'TemplateStringsArray': raw, concat, join, slice, and 15 more. TS2345

Reproduction:
const Test = styled("div")(() => {
const attributes = {
textAlign: "center",
};
return {
...attributes,
};
});
Problem description:
The described code seems to be valid TypeScript Code, but for some reason this is not compiled. If I skip TypeScript checks, the code is compiled just fine.
Suggested solution:
?
EDIT: Added solution to my problem at the end of this post
I'm having the same issue. It is very strange. For me it only happens in some files and not others.
I have a file typings/index.d.ts:
interface Themed {
theme?: any
}
Then I have a file components/H1.tsx:
import styled from '@emotion/styled'
interface Props extends Themed {
uppercase?: boolean
thin?: boolean
}
const H1 = styled('h1')<Props>(
props => ({ <-- VSCode is complaining about this block of code
color: props.theme.colorBlack,
fontFamily: props.theme.fontSansSerif,
fontSize: props.theme.fontSizeH1,
letterSpacing: props.theme.letterSpacingNormal,
}),
props =>
props.uppercase && {
textTransform: 'uppercase',
},
props =>
props.thin && {
fontWeight: '300',
letterSpacing: '0.6px',
}
)
H1.displayName = 'typography.H1'
export default H1
I'm getting the following error in VSCode (but the site compiles and works fine):
[ts]
Argument of type '(props: Props & { theme: any; }) => { color: any; fontFamily: any; fontSize: any; letterSpacing: any; }' is not assignable to parameter of type 'TemplateStringsArray'.
Type '(props: Props & { theme: any; }) => { color: any; fontFamily: any; fontSize: any; letterSpacing: any; }' is missing the following properties from type 'TemplateStringsArray': raw, concat, join, slice, and 16 more. [2345]
---
(parameter) props: Props & {
theme: any;
}
I have another file components/buttons/Button.tsx which is build in the same way like H1.tsx and that file does not throw any errors in VSCode.
SOLUTION: In my case, through some crazy trial and error I found out that fontWeight must be lighter and not 300. This is some of those cases where Typescript sends you off into a completely wrong direction with a super misleading error message :(
See #1125. It's about TS rather about Emotion.
I think what's going on here is the textAlign property of attributes is being inferred as string, but the textAlign property in csstype is a union of string literals, which string is not assignable to.
It should infer correctly if you provide a type annotation:
import * as CSS from 'csstype';
const Test = styled("div")(() => {
const attributes: CSS.Properties = {
textAlign: "center",
};
return {
...attributes,
};
});
Alternatively, once https://github.com/Microsoft/TypeScript/pull/29510 is available then the following should also work:
const Test = styled("div")(() => {
const attributes = {
textAlign: "center",
} as const;
return {
...attributes,
};
});
I ended up making the type of the prop a union of the only cases I needed:
const Side = styled('div')<{ side?: 'left' | 'right' }>(
({ side = 'left' }) => ({
flexBasis: '50%',
flexGrow: 1,
textAlign: side,
}),
)
I think what's going on here is the textAlign property of attributes is being inferred as string, but the textAlign property in csstype is a union of string literals, which string is not assignable to.
import * as CSS from 'csstype'; const Test = styled("div")(() => { const attributes: CSS.Properties = { textAlign: "center", }; return { ...attributes, }; });
Why doesn't this work if you just return attributes? What difference does spreading it into a new object make? It feels like we're just using some indirection to trick TypeScript here.
If the error was as simple as string not being assignable to a union type of string literals, wouldn't the typescript error just say that instead of referencing missing array methods / TemplateStringsArray?
Also maybe slightly off topic, but is it really feasible to type everything as CSS.Properties from csstype? What about component selectors? I'm surprised there isn't a global css type exported by emotion itself.
Why doesn't this work if you just return attributes?
I expect that it would work in this case. Have you tested it?
It feels like we're just using some indirection to trick TypeScript here.
I don't think that typescript is being tricked here.
If the error was as simple as string not being assignable to a union type of string literals, wouldn't the typescript error just say that instead of referencing missing array methods / TemplateStringsArray?
Not necessarily. These kind of error messages can happen when testing assignability to a union type - because A is assignable to B | C if A is assignable to B or A is assignable to C, first A is checked for assignability to B, which fails, then A is checked for assignability to C, which also fails. The error message that's generated is for not being assignable to C, even though the type that you wanted it to be assignable to was B.
Also maybe slightly off topic, but is it really feasible to type everything as CSS.Properties from csstype? What about component selectors? I'm surprised there isn't a global css type exported by emotion itself.
You can use const contexts now, as in my second example above.
This is a "limitation" of TS - described by several people in this thread. You just have to "narrow" down the type of those object properties to things actually accepted by CSS (string is just too broad of a type for this). For this you can use in an example const assertions, assigning object to a CSS.Properties etc.
Most helpful comment
I think what's going on here is the
textAlignproperty ofattributesis being inferred asstring, but thetextAlignproperty in csstype is a union of string literals, whichstringis not assignable to.It should infer correctly if you provide a type annotation:
Alternatively, once https://github.com/Microsoft/TypeScript/pull/29510 is available then the following should also work: