fix(nuxt): improved typing support for app config (#20526)

This commit is contained in:
Daniel Roe 2023-04-26 14:30:05 +01:00 committed by GitHub
parent a21a520736
commit dd0d13d425
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 10 deletions

View File

@ -222,15 +222,17 @@ declare const inlineConfig = ${JSON.stringify(nuxt.options.appConfig, null, 2)}
type ResolvedAppConfig = Defu<typeof inlineConfig, [${app.configs.map((_id: string, index: number) => `typeof cfg${index}`).join(', ')}]>
type IsAny<T> = 0 extends 1 & T ? true : false
type MergedAppConfig<Resolved extends Record<string, any>, Custom extends Record<string, any>> = {
[K in keyof Resolved]: K extends keyof Custom
? IsAny<Custom[K]> extends true
type MergedAppConfig<Resolved extends Record<string, unknown>, Custom extends Record<string, unknown>> = {
[K in keyof (Resolved & Custom)]: K extends keyof Custom
? unknown extends Custom[K]
? Resolved[K]
: Custom[K] extends Record<string, any>
? Resolved[K] extends Record<string, any>
? MergedAppConfig<Resolved[K], Custom[K]>
: Exclude<Custom[K], undefined>
: Exclude<Custom[K], undefined>
: IsAny<Custom[K]> extends true
? Resolved[K]
: Custom[K] extends Record<string, any>
? Resolved[K] extends Record<string, any>
? MergedAppConfig<Resolved[K], Custom[K]>
: Exclude<Custom[K], undefined>
: Exclude<Custom[K], undefined>
: Resolved[K]
}

View File

@ -138,7 +138,9 @@ export interface RuntimeConfig extends RuntimeConfigNamespace {
// -- App Config --
export interface CustomAppConfig { }
export interface CustomAppConfig {
[key: string]: unknown
}
export interface AppConfigInput extends CustomAppConfig {
/** @deprecated reserved */
@ -158,4 +160,6 @@ export interface NuxtAppConfig {
keepalive: boolean | KeepAliveProps
}
export interface AppConfig { }
export interface AppConfig {
[key: string]: unknown
}

View File

@ -145,6 +145,20 @@ export default defineNuxtConfig({
},
telemetry: false, // for testing telemetry types - it is auto-disabled in tests
hooks: {
'schema:extend' (schemas) {
schemas.push({
appConfig: {
someThing: {
value: {
$default: 'default',
$schema: {
tsType: 'string | false'
}
}
}
}
})
},
'prepare:types' ({ tsConfig }) {
tsConfig.include = tsConfig.include!.filter(i => i !== '../../../../**/*')
},

View File

@ -295,6 +295,10 @@ describe('app config', () => {
val: number
}
userConfig: 123 | 456
someThing?: {
value?: string | false,
}
[key: string]: unknown
}
expectTypeOf<AppConfig>().toEqualTypeOf<ExpectedMergedAppConfig>()
})