A while back, I ran into a bit of a headache while working on a project. It was a simple issue, but it was enough to break my flow. I was trying to use CSS custom properties, or CSS variables, directly inside the inline styles of a React component.
The plan was straightforward: I wanted to create some dynamic styles, mostly for
handling themes or changing colors based on a component's state. But the moment
I wrote the code, TypeScript started complaining. I kept getting errors saying
those properties weren't recognized within the CSSProperties interface.
The weird part was that the app actually worked perfectly fine at runtime. There was no actual issue, but the constant red squiggles in my editor were getting annoying. It turns out React's built-in type definitions just don't account for our own custom CSS variables.
My first instinct was to just use any to get it over with, but I'm not a big
fan of that. I prefer using TypeScript when the typing system actually feels
precise. I wanted a way to keep using these variables without throwing away type
safety.
The solution I found was to augment React's CSSProperties interface. I created
a new declaration file, something like src/types/react-augmentations.d.ts, and
added a bit of code to extend the interface so it accepts any string key
starting with --. Then, I just had to make sure that directory was included in
my tsconfig.json.
Once that was done, things were much smoother. I could write code like
<div style={{ '--main-color': props.color } as React.CSSProperties}> without
much friction. It’s been a huge help for building dynamic theme systems.
I did try another approach where I defined every single CSS variable name
explicitly to be even more type-safe, only allowing things like --brand-color
or --bg-primary. But honestly, that felt too restrictive. When it comes to
CSS, you need a bit of freedom. It makes more sense to let CSS variables work
the way they were intended, as long as TypeScript stops flagging them as errors.
Not everything needs to be wrapped in incredibly rigid type rules, but giving these custom variables some breathing room has made my workflow much more comfortable. Of course, this approach has its downsides if you don't keep your project structure organized, but overall, it's been a lifesaver.
I'll leave it there.