Better TypeScript setup for themes
See original GitHub issueI would like to suggest an improved TypeScript theming setup.
Currently, the docs suggest duplicating your theme: creating one in theme.ts
with the values and another in a styled.d.ts
declarations file. This has current setup has two limitations.
- It isn’t DRY - duplication over these two seperate files is annoying to type out.
- Types are vague - You should not only get the name and type (e.g. string) in your autocomplete but also the value (e.g.
hsl(200, 12%, 17%)
).
I’ve found a setup that works better for me, which you can find here on my personal website. This setup has less duplication, keeps all your theming in one file and gives you more informative autocomplete.
First, you type-cast your values so that you get more informative autocomplete:
const theme = {
// blues
b100: 'hsl(221,100%,11%)' as 'hsl(221,100%,11%)',
b200: 'hsl(212,80%,20%)' as 'hsl(212,80%,20%)',
b300: 'hsl(207,84%,24%)' as 'hsl(207,84%,24%)',
b400: 'hsl(208,60%,35%)' as 'hsl(208,60%,35%)',
b500: 'hsl(206,61%,40%)' as 'hsl(206,61%,40%)',
b600: 'hsl(205,53%,48%)' as 'hsl(205,53%,48%)',
b700: 'hsl(205,56%,57%)' as 'hsl(205,56%,57%)',
b800: 'hsl(206,68%,71%)' as 'hsl(206,68%,71%)',
b900: 'hsl(208,82%,85%)' as 'hsl(208,82%,85%)',
}
Second, you import this theme file and extend it, rather than typing out all your values again:
// import original module declarations
import 'styled-components'
// import your custom theme
import theme from '../utils/theme'
// extend the module declarations using custom theme type
type Theme = typeof theme
declare module 'styled-components' {
export interface DefaultTheme extends Theme {}
}
That’s it!
I think this is a much better way to type your theme and I’d be happy to go and make a PR for the docs if the team agrees.
My one question is about interface DefaultTheme extends Theme {}
. This gives me a eslint error with my current setup that warns me about empty themes. However, I can’t think of a better way to rename Theme to DefaultTheme so I’m sticking with it for now.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:152
- Comments:7
Top GitHub Comments
Just wanted to say thanks for writing this up, it was immediately useful and does exactly what I need!
We can remove the duplicate code:
For a flat object, use a single
enum
:For nested objects, use multiple enums inside the theme object.
For nested arrays, use
as const
: