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) => tconst theme = makeTheme({colors: {background: 'white',text: 'black',blue: {light: '#187abf',dark: '#235a97',},},})export type ExactTheme = typeof theme// No errorconst 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
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 errorreturn <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]) }}/>)
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