Skip to content

Commit ffadf2b

Browse files
baffaloppfngaidakovRobinMalfait
authored andcommitted
Improve resolveConfig return type: merge themes (#12272)
* Generate types: do not intersect with Config theme type when generating DefaultTheme * Merge default theme in ResolvedConfig * UnwrapResolvables on theme.extend as well * Apply extend to overrides and default theme * Omit extend from DefaultTheme * Relax generic constraints, better generic variable names * Fall back to ThemeConfig if key not in DefaultTheme * Split out ThemeConfigCustomizable to avoid anys in ThemeConfigResolved * Allow custom theme properties * handle TypeScript error * apply prettier formatting * update changelog * change type name --------- Co-authored-by: Nikita Gaidakov <[email protected]> Co-authored-by: Robin Malfait <[email protected]>
1 parent ac171f0 commit ffadf2b

File tree

4 files changed

+28
-8
lines changed

4 files changed

+28
-8
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Don’t add spaces to negative numbers following a comma ([#12324](https://github.com/tailwindlabs/tailwindcss/pull/12324))
1313
- Don't emit `@config` in CSS when watching via the CLI ([#12327](https://github.com/tailwindlabs/tailwindcss/pull/12327))
14+
- Improve types for `resolveConfig` ([#12272](https://github.com/tailwindlabs/tailwindcss/pull/12272))
1415

1516
## [3.3.5] - 2023-10-25
1617

resolveConfig.d.ts

+22-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,30 @@
1-
import type { Config, ResolvableTo } from './types/config'
1+
import { Config, ResolvableTo, ThemeConfig } from './types/config'
2+
import { DefaultTheme } from './types/generated/default-theme'
3+
import { DefaultColors } from './types/generated/colors'
4+
5+
type ResolvedConfig<T extends Config> = Omit<T, 'theme'> & {
6+
theme: MergeThemes<
7+
UnwrapResolvables<Omit<T['theme'], 'extend'>>,
8+
T['theme'] extends { extend: infer TExtend } ? UnwrapResolvables<TExtend> : {}
9+
>
10+
}
211

312
type UnwrapResolvables<T> = {
413
[K in keyof T]: T[K] extends ResolvableTo<infer R> ? R : T[K]
514
}
615

7-
type ResolvedConfig<T extends Config> = Omit<T, 'theme'> & {
8-
theme: UnwrapResolvables<T['theme']>
16+
type ThemeConfigResolved = UnwrapResolvables<ThemeConfig>
17+
type DefaultThemeFull = DefaultTheme & { colors: DefaultColors }
18+
19+
type MergeThemes<Overrides extends object, Extensions extends object> = {
20+
[K in keyof ThemeConfigResolved | keyof Overrides]: (K extends keyof Overrides
21+
? Overrides[K]
22+
: K extends keyof DefaultThemeFull
23+
? DefaultThemeFull[K]
24+
: K extends keyof ThemeConfigResolved
25+
? ThemeConfigResolved[K]
26+
: never) &
27+
(K extends keyof Extensions ? Extensions[K] : {})
928
}
1029

1130
declare function resolveConfig<T extends Config>(config: T): ResolvedConfig<T>

scripts/generate-types.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,8 @@ fs.writeFileSync(
9191
path.join(process.cwd(), 'types', 'generated', 'default-theme.d.ts'),
9292
prettier.format(
9393
`
94-
import { Config } from '../../types'
9594
type CSSDeclarationList = Record<string, string>
96-
export type DefaultTheme = Config['theme'] & { ${defaultThemeTypes} }
95+
export type DefaultTheme = { ${defaultThemeTypes} }
9796
`,
9897
{
9998
semi: false,

types/config.d.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ type Screen = { raw: string } | { min: string } | { max: string } | { min: strin
7979
type ScreensConfig = string[] | KeyValuePair<string, string | Screen | Screen[]>
8080

8181
// Theme related config
82-
interface ThemeConfig {
82+
export interface ThemeConfig {
8383
// Responsiveness
8484
screens: ResolvableTo<ScreensConfig>
8585
supports: ResolvableTo<Record<string, string>>
@@ -234,8 +234,9 @@ interface ThemeConfig {
234234
transitionDuration: ResolvableTo<KeyValuePair>
235235
willChange: ResolvableTo<KeyValuePair>
236236
content: ResolvableTo<KeyValuePair>
237+
}
237238

238-
// Custom
239+
interface CustomThemeConfig extends ThemeConfig {
239240
[key: string]: any
240241
}
241242

@@ -358,7 +359,7 @@ interface OptionalConfig {
358359
future: Partial<FutureConfig>
359360
experimental: Partial<ExperimentalConfig>
360361
darkMode: Partial<DarkModeConfig>
361-
theme: Partial<ThemeConfig & { extend: Partial<ThemeConfig> }>
362+
theme: Partial<CustomThemeConfig & { extend: Partial<CustomThemeConfig> }>
362363
corePlugins: Partial<CorePluginsConfig>
363364
plugins: Partial<PluginsConfig>
364365
// Custom

0 commit comments

Comments
 (0)