Skip to content

Commit

Permalink
Add more explicit types for the default theme (#8780)
Browse files Browse the repository at this point in the history
* Add more explicit types for the default theme

* Update changelog

* Cleanup

* Cleanup code a bit

* Add special cases for a few keys

* Fix order
  • Loading branch information
thecrypticace committed Jul 7, 2022
1 parent 6e75e6e commit 62f0791
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Don’t prefix selectors in arbitrary variants ([#8773](https://github.com/tailwindlabs/tailwindcss/pull/8773))
- Add support for alpha values in safe list ([#8774](https://github.com/tailwindlabs/tailwindcss/pull/8774))
- Support default `font-weight`s in font size utilities ([#8763](https://github.com/tailwindlabs/tailwindcss/pull/8763))
- Add more explicit types for the default theme ([#8780](https://github.com/tailwindlabs/tailwindcss/pull/8780))

## [3.1.4] - 2022-06-21

Expand Down
3 changes: 2 additions & 1 deletion defaultTheme.d.ts
@@ -1,3 +1,4 @@
import type { Config } from './types/config'
declare const theme: Config['theme']
import { DefaultTheme } from './types/generated/default-theme'
declare const theme: Config['theme'] & DefaultTheme
export = theme
53 changes: 53 additions & 0 deletions scripts/generate-types.js
@@ -1,8 +1,10 @@
import prettier from 'prettier'
import { corePlugins } from '../src/corePlugins'
import colors from '../src/public/colors'
import defaultTheme from '../src/public/default-theme'
import fs from 'fs'
import path from 'path'
import * as types from './type-utils'

fs.writeFileSync(
path.join(process.cwd(), 'types', 'generated', 'corePluginList.d.ts'),
Expand Down Expand Up @@ -50,3 +52,54 @@ fs.writeFileSync(
}
)
)

const defaultThemeTypes = Object.entries(defaultTheme)
.map(([name, value]) => {
// Special cases for slightly more accurate types
if (name === 'keyframes') {
return [name, `Record<${types.forKeys(value)}, Record<string, CSSDeclarationList>>`]
}

if (name === 'fontSize') {
return [name, `Record<${types.forKeys(value)}, [string, { lineHeight: string }]>`]
}

// General cases
if (typeof value === 'string') {
return [name, `string`]
}

if (typeof value === 'function') {
return [name, null]
}

if (typeof value === 'object') {
if (Object.keys(value).length === 0) {
return [name, null]
}

return [name, types.forValue(value)]
}

return [name, `unknown`]
})
.filter(([, type]) => type !== null)
.map(([name, type]) => `${name}: ${type}`)
.join('\n')

fs.writeFileSync(
path.join(process.cwd(), 'types', 'generated', 'default-theme.d.ts'),
prettier.format(
`
import { Config } from '../../types'
type CSSDeclarationList = Record<string, string>
export type DefaultTheme = Config['theme'] & { ${defaultThemeTypes} }
`,
{
semi: false,
singleQuote: true,
printWidth: 100,
parser: 'typescript',
}
)
)
27 changes: 27 additions & 0 deletions scripts/type-utils.js
@@ -0,0 +1,27 @@
export function union(types) {
return [...new Set(types)].join(' | ')
}

export function unionValues(values) {
return union(values.map(forValue))
}

export function forKeys(value) {
return union(Object.keys(value).map((key) => `'${key}'`))
}

export function forValue(value) {
if (Array.isArray(value)) {
return `(${unionValues(value)})[]`
}

if (typeof value === 'object') {
return `Record<${forKeys(value)}, ${unionValues(Object.values(value))}>`
}

if (typeof value === 'string') {
return `string`
}

return `any`
}

0 comments on commit 62f0791

Please sign in to comment.