N
Nuxtβ€’8mo ago
Alejandro Mery

type checking custom AppConfig entries

https://nuxt.com/docs/guide/directory-structure/app-config#app-config-output tells to use declare module to extend nuxt/schema's AppConfigInput on the index.d.ts file... where is that? I tried in src/composables/useFoo.ts instead, src/composables/index.d.ts and src/index.d.ts, but neither validates my custom entry in app.config.ts. where should this be done I? what if there are other declarations and exports on the same file?
Nuxt
app.config.ts Β· Nuxt Directory Structure
Expose reactive configuration within your application with the App Config file.
28 Replies
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
I'm currently exporting a composable to access it, validating the type, but it feels wrong.
export interface myThingAppConfig {}

export function useMyThing(): myThingAppConfig {
const { myThing } = useAppConfig();
return myThing
}
export interface myThingAppConfig {}

export function useMyThing(): myThingAppConfig {
const { myThing } = useAppConfig();
return myThing
}
but the actual type of myThing will be inferred from the data on app.config.ts instead of from the extended type.
declare module 'nuxt/schema' {
interface AppConfigInput {
myThing: myThingAppConfig,
}
}

export {}
declare module 'nuxt/schema' {
interface AppConfigInput {
myThing: myThingAppConfig,
}
}

export {}
pyplacca
pyplaccaβ€’8mo ago
the index.d.ts is a file you create at the root of your project
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
thanks. can I use types from composables there?
pyplacca
pyplaccaβ€’8mo ago
if it doesn't augment the types generated by nuxt, you'd rather want to export your types from the types folder
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
thanks
pyplacca
pyplaccaβ€’8mo ago
welcome
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
I'm exporting the config type from src/types/index.ts and the composable is happy. then I created the following index.d.ts on the same directory of nuxt.config.ts :
declare module 'nuxt/schema' {
interface AppConfigInput {
myThing: myThingConfig
}
}

export {};
declare module 'nuxt/schema' {
interface AppConfigInput {
myThing: myThingConfig
}
}

export {};
but on src/app.config.ts the field is still inferred and accepting anything 😦
export default defineAppConfig({
myThing: {
invalid: 'field',
}
})
export default defineAppConfig({
myThing: {
invalid: 'field',
}
})
any idea what am I missing to get AppConfigInput extended?
pyplacca
pyplaccaβ€’8mo ago
Is app.config.ts not supposed to be at the root level? Same level as nuxt.config.ts
pyplacca
pyplaccaβ€’8mo ago
Also, the interface should be AppConfig instead of AppConfigInput
Nuxt
app.config.ts Β· Nuxt Directory Structure
Expose reactive configuration within your application with the App Config file.
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
thanks, still not type-checking though 🫀
pyplacca
pyplaccaβ€’8mo ago
Care to share screenshots of your directory tree, index.d.ts file, and app.config.ts file? Before that try restarting the dev server and see if it works
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
a critical bit that can be a cause of confusion is srcDir on nuxt.config.ts, but src/app.config.ts data is being loaded so that place is correct.
export default defineNuxtConfig({
srcDir: 'src',
// ...
});
export default defineNuxtConfig({
srcDir: 'src',
// ...
});
my tree looks like:
$ tree
.
β”œβ”€β”€ eslint.config.mjs
β”œβ”€β”€ files.go
β”œβ”€β”€ index.d.ts
β”œβ”€β”€ lcweb-client.code-workspace
β”œβ”€β”€ Makefile
β”œβ”€β”€ middleware.go
β”œβ”€β”€ node_modules
β”‚Β Β  β”œβ”€β”€ eslint -> ../../../node_modules/.pnpm/[email protected]/node_modules/eslint
...
β”œβ”€β”€ package.json
β”œβ”€β”€ src
β”‚Β Β  β”œβ”€β”€ app.config.ts
β”‚Β Β  β”œβ”€β”€ app.vue
β”‚Β Β  β”œβ”€β”€ assets
β”‚Β Β  β”œβ”€β”€ components
β”‚Β Β  β”œβ”€β”€ composables
β”‚Β Β  β”œβ”€β”€ error.vue
β”‚Β Β  β”œβ”€β”€ layouts
β”‚Β Β  β”œβ”€β”€ middleware
β”‚Β Β  β”œβ”€β”€ pages
β”‚Β Β  β”œβ”€β”€ public
β”‚Β Β  β”œβ”€β”€ stores
β”‚Β Β  └── types
β”‚Β Β  β”œβ”€β”€ config.ts
β”‚Β Β  └── index.ts
β”œβ”€β”€ tailwind.config.ts
└── tsconfig.json
$ tree
.
β”œβ”€β”€ eslint.config.mjs
β”œβ”€β”€ files.go
β”œβ”€β”€ index.d.ts
β”œβ”€β”€ lcweb-client.code-workspace
β”œβ”€β”€ Makefile
β”œβ”€β”€ middleware.go
β”œβ”€β”€ node_modules
β”‚Β Β  β”œβ”€β”€ eslint -> ../../../node_modules/.pnpm/[email protected]/node_modules/eslint
...
β”œβ”€β”€ package.json
β”œβ”€β”€ src
β”‚Β Β  β”œβ”€β”€ app.config.ts
β”‚Β Β  β”œβ”€β”€ app.vue
β”‚Β Β  β”œβ”€β”€ assets
β”‚Β Β  β”œβ”€β”€ components
β”‚Β Β  β”œβ”€β”€ composables
β”‚Β Β  β”œβ”€β”€ error.vue
β”‚Β Β  β”œβ”€β”€ layouts
β”‚Β Β  β”œβ”€β”€ middleware
β”‚Β Β  β”œβ”€β”€ pages
β”‚Β Β  β”œβ”€β”€ public
β”‚Β Β  β”œβ”€β”€ stores
β”‚Β Β  └── types
β”‚Β Β  β”œβ”€β”€ config.ts
β”‚Β Β  └── index.ts
β”œβ”€β”€ tailwind.config.ts
└── tsconfig.json
the root level index.d.ts contains
export {};

declare module 'nuxt/schema' {
interface AppConfig {
lw: logicWashAppConfig
}
}
export {};

declare module 'nuxt/schema' {
interface AppConfig {
lw: logicWashAppConfig
}
}
and src/app.config.ts
// ...
export default defineAppConfig({
lw: {
icons: {
'config': 'i-ph-file-bold',
'config-xml': 'i-bi-filetype-xml',
// ...
'checked': 'foo',
'invalid': 123,
},
ui: {
config: {
card: {
wrapper: 'w-full lg:max-w-5xl',
},
},
},
},
ui: {
primary,
gray,

variables: {
light: {
background: lightBackground,
foreground: 'var(--color-gray-900)',
},
dark: {
background: darkBackground,
foreground: 'var(--color-gray-200)',
},
},

icons: {
dynamic: true,
},

dashboard: {
card: {
wrapper: 'shadow-xl mt-2 bg-white/95 dark:bg-gray-900/95',
},
},
},
});
// ...
export default defineAppConfig({
lw: {
icons: {
'config': 'i-ph-file-bold',
'config-xml': 'i-bi-filetype-xml',
// ...
'checked': 'foo',
'invalid': 123,
},
ui: {
config: {
card: {
wrapper: 'w-full lg:max-w-5xl',
},
},
},
},
ui: {
primary,
gray,

variables: {
light: {
background: lightBackground,
foreground: 'var(--color-gray-900)',
},
dark: {
background: darkBackground,
foreground: 'var(--color-gray-200)',
},
},

icons: {
dynamic: true,
},

dashboard: {
card: {
wrapper: 'shadow-xl mt-2 bg-white/95 dark:bg-gray-900/95',
},
},
},
});
pyplacca
pyplaccaβ€’8mo ago
Having the export statement at the top of the file could be the problem
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
I had it at the bottom, just moved it when looking at the files generated on .nuxt/. I'll move it back to the bottom. same result btw
pyplacca
pyplaccaβ€’8mo ago
Okay. I’m not sure where nuxt looks to find the index.d.ts file, but if your srcDir is set to src I’m guessing the index.d.ts file would need to be in that folder.
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
tried both 😦
pyplacca
pyplaccaβ€’8mo ago
πŸ€” Can you create a repro on stackblitz for instance so I check it out?
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
GitHub
GitHub - amery/go-nuxt-template at issue-app.config.ts
Contribute to amery/go-nuxt-template development by creating an account on GitHub.
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
issue-app.config.ts branch, web/client subdirectory https://stackblitz.com/~/github.com/amery/go-nuxt-template
pyplacca
pyplaccaβ€’8mo ago
@mercs600, here
// index.d.ts
export {};

declare module '@nuxt/schema' {
interface AppConfigInput {
lw: logicWashAppConfig
}
}
// index.d.ts
export {};

declare module '@nuxt/schema' {
interface AppConfigInput {
lw: logicWashAppConfig
}
}
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
I was using AppConfigInput initially 😭 where did you place the file? root or srcDir? like this? @pyplacca
diff --git a/web/client/src/index.d.ts b/web/client/src/index.d.ts
index c9aef34..dbac142 100644
--- a/web/client/src/index.d.ts
+++ b/web/client/src/index.d.ts
@@ -1,9 +1,7 @@
-import type { myThingAppConfig } from './types';
+export {};

declare module 'nuxt/schema' {
- interface AppConfig {
+ interface AppConfigInput {
myThing?: myThingAppConfig
}
}
-
-export {}
diff --git a/web/client/src/index.d.ts b/web/client/src/index.d.ts
index c9aef34..dbac142 100644
--- a/web/client/src/index.d.ts
+++ b/web/client/src/index.d.ts
@@ -1,9 +1,7 @@
-import type { myThingAppConfig } from './types';
+export {};

declare module 'nuxt/schema' {
- interface AppConfig {
+ interface AppConfigInput {
myThing?: myThingAppConfig
}
}
-
-export {}
app.config.ts still thinks myThing.something is boolean, ignoring the type 😭
pyplacca
pyplaccaβ€’8mo ago
Anywhere works. Take note of the module name @nuxt/schema @Alejandro MeryπŸ‘†
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
the @!!!! thank you so much @pyplacca
pyplacca
pyplaccaβ€’8mo ago
The previous code would work in most cases, but this is a weird behaviour caused by the nuxt ui module Glad I could help, @Alejandro Mery
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
I just noticed checking doesn't work on the LAST entry. is this the weird behaviour you mentioned?
pyplacca
pyplaccaβ€’8mo ago
Which last entry?
Alejandro Mery
Alejandro MeryOPβ€’8mo ago
my fault, it caught a previous typo and didn't continue checking thanks again. I'm closing this now πŸ™
pyplacca
pyplaccaβ€’8mo ago
Alright. It was a pleasure helping out. I learnt a couple of new stuff myself 😊
Want results from more Discord servers?
Add your server