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.

Add stricter type support

See original GitHub issue

I’m still waiting on https://github.com/system-ui/theme-ui/pull/1090 to merge, and it seems to be getting hung up.

I think it might be time to upstream theme-ui on types for certain things.

I have 2 goals:

  • Provide stricter types that match Dripsy, such as Theme['customFonts']
  • Let users use declaration merging to type useDripsyTheme.
    • I’d like to achieve the same with the sx prop, but it’s too complicated so I’ll wait for the PR above.

1) Edit the default Theme type, name it DripsyTheme

For starters, I’d like to override the default Theme type exported from theme-ui, which does not include dripsy’s customFonts key in the theme.

As we can see here in this app by @byCedric, customFonts isn’t included in the type, so you need to either ignore Theme, or make it a separate type. This doesn’t seem ideal.

// types.ts
import type { Theme } from 'theme-ui'

export interface BaseDripsyTheme extends Theme { customFonts: { ... } }

Custom Font type implementation

Since Dripsy has strict requirements for custom fonts, it would be nice to enforce them with types too:

export interface BaseDripsyTheme<FontFamilyKeys extends string> extends Theme {
  customFonts?: { [key in FontFamilyKeys]?: Record<string, string> }
  fonts?: {
    [key: string]: FontFamilyKeys | undefined
    ['root']?: FontFamilyKeys
  }
}

Unfortunately, it seems like this code sample doesn’t actually work as intended, so I’d love suggestions on that.

2) Provide strict types for useDripsyTheme

As it stands, useDripsyTheme has relatively weak typings. At the very least, I’d like it to piggy back off of 1) above, like so:

// use-dripsy-theme
import { BaseDripsyTheme } from './types.ts'

export default function useDripsyTheme() {
  return (useThemeUI() as any) as Omit<ReturnType<typeof useThemeUi>, 'theme'> & { theme: BaseDripsyTheme }
}

Here, we at least get the customFonts field with useDripsyTheme.

However, I think we could take it a step further with declaration merging. This is what https://github.com/system-ui/theme-ui/pull/1090 intends to achieve for the sx prop. In the meantime, I think we can hack our way around it for useDripsyTheme.

Strict types implementation

Imagine we have this theme:

const theme = {
  colors: {
    primary: 'red',
    'primary-dark': 'darkred'
  }
}

A fair expectation from the user should be this:

const { colors } = useDripsyTheme().theme

const textColor = colors.primary // red

I think it could be achieved with this kind of solution:

Step 1: Dripsy creates a makeTheme function:

An example looks like this from theme-ui’s upcoming PR.

// this is from #1 up above
import { DripsyTheme } from './types'

export const makeTheme = <T extends DripsyTheme>(t: T) => t

Step 2: Dripsy exports CustomDripsyTheme

Theme-ui plans to call this UserTheme, so once they do, we can merge them somehow, but this way we don’t collide.

/**
 * Can be augmented by users to inject their exact theme into Dripsy types.
 */
export interface CustomDripsyTheme {}

Step 3: Users create their theme with makeTheme:

const myTheme = makeTheme({
  colors: {
    primary: 'red',
    'primary-dark': 'darkred'
  }
})

type MyTheme = typeof myTheme
declare module 'dripsy' {
  // this overrides the empty CustomDripsyTheme that Dripsy exports
  export interface CustomDripsyTheme extends MyTheme {}
}

Step 4. Make FinalDripsyTheme

We can combine the original BaseDripsyTheme with CustomDripsyTheme:

import type { Theme } from 'theme-ui'

export interface BaseDripsyTheme extends Theme { customFonts: { ... } }

export type Assign<T, U> = {
  [P in keyof (T & U)]: P extends keyof U
    ? U[P]
    : P extends keyof T
    ? T[P]
    : never
}

export interface DripsyTheme extends Assign<BaseDripsyTheme, CustomDripsyTheme> {}

// For backwards-compatibility, name Theme too
export type Theme = DripsyTheme

The code above is taken from theme-ui here.

Now that we have this DripsyTheme created, we can use that in useDripsyTheme:

// use-dripsy-theme
- import { BaseDripsyTheme } from './types.ts'
+import { DripsyTheme } from './types.ts'
// use-dripsy-theme

export default function useDripsyTheme() {
  return (useThemeUI() as any) as Omit<ReturnType<typeof useThemeUi>, 'theme'> & { theme: DripsyTheme }
}

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:4
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
nandorojocommented, Apr 28, 2021

Yeah, I haven’t really had time to work on this. At the moment, I’m just using this in my app:


import { useDripsyTheme } from 'dripsy'
import type { DripsyTheme } from './index'

export default function useTheme() {
  return (useDripsyTheme().theme as any) as DripsyTheme
}
1reaction
JackCAcommented, Apr 28, 2021

@nandorojo it looks like #74, does that help push this along at all?

PS: You’ve been doing really great work on the recent releases!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Angular CLI Strict Mode
To opt into the strict mode, you need to create a new Angular CLI app, ... For more details, check “To Type or...
Read more >
strict - TSConfig Option - TypeScript
All of the common types in TypeScript ... How to provide a type shape to JavaScript objects ... How TypeScript infers types based...
Read more >
C++ Applications Use STRICT Type Checking - RAD Studio
Rebuild your project and correct any errors that appear as the result of type checking, especially in calls to Windows procedures. Adding the...
Read more >
The --strict Compiler Option in TypeScript - Marius Schulz
TypeScript 2.3 introduced a new --strict compiler option that enables a number of other compiler options related to stricter type checking.
Read more >
TypeScript strictly typed: strict mode is not enough - Medium
Note that TypeScript does not ask to add an explicit type for the ... And you want to support my open source work...
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