Skip to content
Theme UI
GitHub

TypeScript

Theme UI is written in TypeScript.

While most APIs in Theme UI should just work in TypeScript, there are a few advanced use cases which will differ slightly. This guide is intended to cover those use cases.

Exact theme type

The Theme type represents all possible themes.

It might be what you need when you're writing a library of reusable components or an app where the theme object is provided by the user and kept in the database. However, it's not the most convenient way to think about the theme, when building a blog or a landing page.

To know the exact type of your particular theme on type level, you can use an identity "constructor" function to narrow the type.

const makeTheme = <T extends Theme>(t: T) => t
const theme = makeTheme({
colors: {
background: 'white',
text: 'black',
blue: {
light: '#187abf',
dark: '#235a97',
},
},
})
export type ExactTheme = typeof theme
// No error
const lightBlue = theme.colors.blue.light

You can then reexport useThemeUI hook with narrowed type.

import { ThemeUIContextValue } from 'theme-ui'
interface ExactContextValue extends Omit<ThemeUIContextValue, 'theme'> {
theme: ExactTheme
}
export const useTheme = (useThemeUI as unknown) as () => ExactContextValue

Try it on CodeSandbox.

Accessing optional properties

Because all properties of Theme are optional, accessing them requires usage of get function.

/** @jsxImportSource theme-ui */
import { Theme } from 'theme-ui'
const theme: Theme = {
space: [0, 8, 16, 32, 64, 128, 256],
sizes: [0, 8, 16, 32, 64, 128, 256],
}
// Type error on `theme.space` and `theme.sizes`.
// Object is possibly 'undefined'.ts(2532)
return <div sx={{ size: (t) => t.space[3] + t.sizes[5] }} />
/** @jsxImportSource theme-ui */
import { Theme, get } from 'theme-ui'
// No error
return <div sx={{ size: (t) => get(t, 'space.3') + get(t, 'sizes.5') }} />

Properties of scales can be accessed with optional chaining. Values under numeric keys can be accessed with bracket notation.

/** @jsxImportSource theme-ui */
const parse = (x: unknown) => parseInt(String(x))
return (
<div sx={{
size: (t) => parse(t.space?.[3]) + parse(t.sizes?.[5]) }}
/>
)

Try it on CodeSandbox.

Additional properties in the theme

If you need additional properties in theme object, you can add them with declaration merging.

interface MySyntaxHighlightingTheme {
foreground: string
}
declare module 'theme-ui' {
interface Theme {
syntaxHighlighting: MySyntaxHighlightingTheme
}
}
const theme: Theme = {
syntaxHighlighting: {
foreground: '#222',
},
}
const syntaxHighlighting = theme.syntaxHighlighting

Try it in TypeScript Playground.

Edit the page on GitHub
Previous:
Global Styles
Next:
Recipes