How to make a dictionary of Base Web custom theme styles type safe

94 Views Asked by At

I'm using the Base Web UI component framework with my Next.js project. I have extended the Theme object to add some custom colors. I did so in accordance with the instructions here: https://baseweb.design/guides/theming/#extending-the-theme-type. Note, the docs say the theme type is called ThemeT, but actually it appears to be called Theme (perhaps the documentation is outdated?)

Anyhoo ...It works fine with a basic use case like this:

import { themedUseStyletron as useStyletron} from "../../Shared/Theme";

const MyComponent = props => {
    const [css, theme] = useStyletron()
    return (
        <div className={css({background: theme.postItYellow})}>Hello!</div>
    )
}

postItYellow is a custom color that I added to the extended theme. Typescript does not complain about this. We're all good. The problem is, I have some code where I select a color from the theme dynamically using a simple dictionary that looks like this:

export const  STATUS_TO_COLOR = {
  TO_DO:  'postItYellow',
  IN_PROGRESS: 'postItBlue',
  DONE: 'postItGreen'
}

If I do something like this:

const MyComponent = props => {
    const [css, theme] = useStyletron()
    return (
        <div className={css({background: `${theme[STATUS_TO_COLOR['TO_DO']]}`,})}>Hello!</div>
    )
}

I get the following error: TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'CustomThemeT'.   No index signature with a parameter of type 'string' was found on type 'CustomThemeT'.

I tried rewriting STATUS_TO_COLOR a couple of different ways in TS but got pretty much the same error. Can someone please point me in the right direction? Humble thanks in advance.

1

There are 1 best solutions below

0
On

I just figured out one way to do this:

export type TaskBackgroundColor = 'postItYellow' | 'postItBlue' | 'postItGreen'

export type BackgroundColorDict = { [key: string] : TaskBackgroundColor}

export const  STATUS_TO_COLOR : BackgroundColorDict = {
    TO_DO:  'postItYellow',
    IN_PROGRESS: 'postItBlue',
    DONE: 'postItGreen'
}

Feel free to post an answer if you know of a more idiomatic or stricter way. TIA!