Reputation: 17239
Using styled-components
, with normal React.js I can do like:
const Container = styled.div({
userSelect: `none !important`,
})
however with TypeScript I get the error:
Argument of type '{ userSelect: string; }' is not assignable to parameter of type 'TemplateStringsArray'.
Object literal may only specify known properties, and 'userSelect' does not exist in type 'TemplateStringsArray'.ts(2345)
What's the best way to fix this?
I don't want to use the styled.div
template strings approach as I find it a lot less flexible.
For example with template strings we can't do things like:
const flex = {
flex: display: flex,
col: flexDirection: `column`
}
const FlexRow = styled.div({
...flex.flex,
})
const FlexCol = styled.div({
...flex.flex,
...flex.col,
})
Upvotes: 5
Views: 4336
Reputation: 2069
I've just come across this question while looking for something slightly related. I know it's resolved but I've used styled-components for quite a while and never have happened to see the object syntax you refer to, I presume this is included to allow adoption from other css-in-js options.
However, the reason for me commenting is your flex example, you could achieve a very similar effect with tagged template literals:
const flex = {
flex: 'display: flex',
col: 'flex-direction: column'
}
const FlexRow = styled.div`
${flex.flex};
`
const FlexCol = styled.div`
${flex.flex};
${flex.col};
`
Happy styled-componenting 🙂
Upvotes: 0
Reputation: 1651
it doesn't recognize the !important
so just cast it to any to quiet typescript.
styled.div({
userSelect: 'none !important' as any
});
its very simple. if you use an ide like atom you can "go to" the type for the userSelect property. The type is UserSelectProperty
and its value must be one of these exactly.
export type Globals = "-moz-initial" | "inherit" | "initial" | "revert" | "unset";
export type UserSelectProperty = Globals | "-moz-none" | "all" | "auto" | "contain" | "element" | "none" | "text";
Since none !important
is not an option, you have to cast it to any.
Upvotes: 4
Reputation: 148980
Update: On further investigation, it appears that @Vincent was on the right track before I figured out what was actually going on.
import styled, { CSSObject } from "styled-components";
const Container = styled.div({
userSelect: "none !important"
} as CSSObject);
Will generate the following error:
Conversion of type '{ userSelect: "none !important"; }' to type 'CSSObject' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type '{ userSelect: "none !important"; }' is not comparable to type 'Properties<string | number>'.
Types of property 'userSelect' are incompatible.
Type '"none !important"' is not comparable to type '"contain" | "all" | "-moz-initial" | "inherit" | "initial" | "revert" | "unset" | "auto" | "none" | "text" | "-moz-none" | "element" | undefined'.ts(2352)
So yes, styled components does indeed support this syntax even in TypeScript, it just doesn't understand the !important
suffix. Here's a slightly modified solution you might prefer:
const important = <T extends string>(s: T): T => `${s} !important` as T;
const Container = styled.div({
userSelect: important("none"),
});
It's a little hacky (casting "none !important"
as "none"
when it clearly isn't), but it keeps your styled CSS props clean and passes the type-checks.
Original Answer: I'm not familiar with that syntax for styled components (it looks a bit like JSS, but not exactly).
I'd recommend using the standard syntax. Styled components are usually written like this:
const Container = styled.div`
user-select: none !important;
`;
Upvotes: 6