question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Usage of Theme UI with TypeScript

See original GitHub issue

TS noob here. I have installed @types/theme-ui as well as have the following in theme.ts:

export const theme = {
  fonts: {
    body:
      'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif',
    heading: '"Avenir Next", sans-serif',
    monospace: 'Menlo, monospace',
  },
  colors: {
    text: '#000',
    background: 'white',
    primary: '#bf1',
  },
  modes: {
    dark: {
      text: '#fff',
      background: '#000',
      primary: '#0cf',
    },
  },
}

How do I convert it to TS so I can get autocomplete?

I tried the following:

import {Theme} from 'theme-ui'

export const theme: Theme = {
  fonts: {
    body:
      'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif',
    heading: '"Avenir Next", sans-serif',
    monospace: 'Menlo, monospace',
  },
  colors: {
    text: '#000',
    background: 'white',
    primary: '#bf1',
  },
  modes: {
    dark: {
      text: '#fff',
      background: '#000',
      primary: '#0cf',
    },
  },
}

But I get red squiggly lines on modes with the error

Object literal may only specify known properties, and ‘modes’ does not exist in type ‘Theme’

I tried finding what should be the type in https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/theme-ui/index.d.ts but I can’t find it. Then I saw https://github.com/system-ui/theme-ui/issues/668 to wonder if it’s even complete. I just want the theme object to have correct keys 😃

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:25 (9 by maintainers)

github_iconTop GitHub Comments

2reactions
hasparuscommented, May 8, 2020

@hasparus basically if you include theme-ui in a project which has TS, for what things you add static typing? Like check out Overmind’s Typescript guide

The perfect case answer would be

You don’t need to worry about it, if you misspell any variable name or mix something up, TypeScript will tell you.

We ain’t there yet. I hope we’ll come closer to this experience with the stable version. Theme UI types in their most basic form should just work ™. It should be as easy and seamless as using @emotion/core.

(@jxnblk correct me if I’m wrong)


A bit off-topic right now, but the Overmind guide you linked may be relevant one day. The declare module trick as seen in Overmind and fp-ts typeclass instances can be used to implement “TypeScript: Type check property values against theme scales” todo @jxnblk mentioned in https://github.com/system-ui/theme-ui/issues/832.

When we’re using Theme UI in statically typed codebase, Ii’s good to notice we have two concepts of theme, ergo two types.

1. The general idea of theme.

This one is interesting for libraries and for apps where user can edit the theme. This is the interface Theme defined in @theme-ui/css.

We can’t read theme.fonts.monospace, because we have no idea if there is a fonts scale in the theme and even if its is, we don’t know if it has anything under monospace key.

We can use optional chaining for fonts (theme?.fonts), but we can’t read monospace because fonts could be an array. This is where get function from lodash or @theme-ui/css is helpful.

2. A particular theme, defined in the source code.

It’s known at compile time, so we’d like to autocomplete keys from scales when the user writes their styles for nicer DX.

  • TS support for this is not implemented yet.
  • It will require some additional “overhead”
    • either by injection of your type into theme-ui types, like in Overmind or fp-ts
    • or by a “theme constructor function” on user side and generics plumbing through theme-ui code.

This is the type we get when we write

const theme = {
  fonts: {
    monospace: 'Fira Code'
  }
} as const

type MyTheme = typeof theme

(as const means “Hey TS, make the type here as narrow as possible!”)

MyTheme is a subtype of Theme, i.e. all specific branded themes are assignable to Theme.

Notice we get no autocomplete inside the theme object in snippet above.

My clumsy fingers do at least two typos per second. This is a serious problem when I post on Twitter, but it doesn’t have to be a problem in my source code. I solved it in my blog with a cleverly typed identity function.

import { Theme } from "theme-ui";

const makeTheme = <ExactTheme extends Theme>(t: ExactTheme): ExactTheme => {
  return t;
};

It allows me to say “my argument t is of type ExactTheme which is a subtype of the Theme I just imported”. After we compile TS it’s just identity, so it can be thrown out by an optimizer (e.g. Closure Compiler Advanced Optimizations).

const theme = makeTheme({
  space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
});

export default theme;
export type MyTheme = typeof theme;

We claim more control over the type of theme. The tradeoff is that we lose extra property checks. i.e.

/* Type '{ spaceX: number[]; }' is not assignable to type 'Theme'.
  Object literal may only specify known properties, but 'spaceX' does not exist in type 'Theme'.
  Did you mean to write 'space'? ts(2322) */
const theme1: Theme = {
  spaceX: [0, 4, 8, 16, 32, 64, 128, 256, 512],
}

/* totally okay, no error */
const theme2 = makeTheme({
  spaceX: [0, 4, 8, 16, 32, 64, 128, 256, 512],
})
1reaction
jxnblkcommented, May 12, 2020

what do you think about making merge public?

If it makes usage easier, I think it could safely be exposed as the “go-to theme merging function” like you mention – it’s only a small/configured wrapper around deepmerge so I don’t think ongoing maintenance would be too much of a hassle

Read more comments on GitHub >

github_iconTop Results From Across the Web

TypeScript - Theme UI
Theme UI is written in TypeScript. While most APIs in Theme UI should just work in TypeScript, there are a few advanced use...
Read more >
TypeScript Theme UI Link - Paul Scanlon
I'll briefly explain those three points. The sx prop is part of the Theme UI JSX pragma and allows you to style any...
Read more >
theme-ui-typescript-tips - CodeSandbox
theme -ui-typescript-tips. 1. Embed Fork Create Sandbox Sign in. Sandbox Info ... Templatetheme-ui-rect; Environmentcreate-react-app ... @theme-ui/css.
Read more >
@types/theme-ui - npm
Stub TypeScript definitions entry for theme-ui, which provides its own types definitions. Latest version: 0.6.0, last published: 2 years ago ...
Read more >
Theme with styled-components and Typescript - Medium
One of its advanced use cases for this library is theming. Theming in styled-components allows your app to support multiple design patterns ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found