Skip to content

fix(types): apply the AppConfig augmentation in apps extending the layer - #1437

Merged
larbish merged 2 commits into
nuxt-content:mainfrom
sisou:fix/app-config-types-in-consumers
Sep 30, 2026
Merged

larbish merged 2 commits into
nuxt-content:mainfrom
sisou:fix/app-config-types-in-consumers

Conversation

@sisou

@sisou sisou commented Sep 8, 2026

Copy link
Copy Markdown

Summary

layer/app/types/index.d.ts has imports and exports, so it is a module — which makes its declare module 'nuxt/schema' block a module augmentation, and those only take effect once something pulls the file into the program. Inside this repo that happens (the layer is a local directory whose files are reachable), so pnpm typecheck is green. In an app that installs docus from npm, nothing imports or references it: the file is in the consumer's tsconfig include, and tsc --listFilesOnly even lists it, but the augmentation never applies.

Every AppConfig field declared in that file is therefore silently missing in consumers, and the app falls back to the shapes generated from nuxt.schema.ts. It's easy to miss because the fallback types are almost right — until one of them isn't.

Since 5.13.0 it isn't. useSeo reads AppConfig['seo']['schema'] (added in #1433), and only app/types/index.d.ts declares schema, so nuxi typecheck now fails in every app extending the layer:

node_modules/docus/app/composables/useSeo.ts(37,53): error TS2339: Property 'schema'
does not exist on type '{ title?: string | undefined; description?: string | undefined; }'
node_modules/docus/app/composables/useSeo.ts(139,41): error TS2339: Property 'schema'
does not exist on type '{ title?: string | undefined; description?: string | undefined; }'

That type is the one generated from layer/nuxt.schema.ts, where seo is just title + description.

Fix

index.d.ts is already reachable in consumers — Nuxt writes /// <reference path="../node_modules/docus/index.d.ts" /> into .nuxt/nuxt.d.ts — so importing the types file from there is enough:

import type {} from './app/types'

One line, no type changes, nothing new shipped (app and index.d.ts are both already in files).

Reproduction

A minimal app is enough — no fixture repo needed:

cd layer && npm pack                 # docus-5.13.0.tgz
mkdir repro && cd repro
# package.json depending on ../docus-5.13.0.tgz + nuxt + vue-tsc + better-sqlite3
# nuxt.config.ts: export default defineNuxtConfig({ extends: ['docus'] })
# tsconfig.json: { "extends": "./.nuxt/tsconfig.json" }
# content/index.md with any front matter
npm install && npx nuxt typecheck

Before: the two useSeo.ts errors above. After: gone.

To confirm the mechanism rather than the symptom, add a marker to the augmentation:

declare module 'nuxt/schema' {
  interface AppConfig {
    zzTest: 'yes'
    // …

and probe it from the app. On main AppConfig['zzTest'] resolves to unknown (it falls through AppConfig's index signature — the augmentation is inert). With this patch it resolves.

Verified

  • pnpm lint — unchanged (0 errors, the pre-existing vue/no-v-html warning)
  • pnpm typecheck — passes
  • Minimal consumer app against a packed build of this branch — both useSeo.ts errors gone

Out of scope

  • App config type: github can't be set to false #1249 / github: false not accepted in type definition #1347 (github: false rejected) is a different mechanism, not fixed here: that error comes from AppConfigInput, which defineAppConfig checks against and which is fed by the generated nuxt.schema.ts types, not by the AppConfig augmentation. Worth a separate fix — either allowing false in nuxt.schema.ts or augmenting AppConfigInput.
  • Four other errors a consumer still sees, all pre-existing and unrelated to this file (part of what Fresh install has 18 type errors #1413 reports): useSeo.ts:172/221 (unhead ResolvableArray for the link/script arrays) and plugins/i18n.ts:52 + useAssistant.ts:59 (i18n.defaultLocale on {}).

Nothing in CI would catch a regression of this, since pnpm typecheck only checks the layer in-repo, where the augmentation does apply. A nuxt typecheck over a small app extending a packed layer would — happy to add one if you want it in this PR.

`layer/app/types/index.d.ts` has imports and exports, so it is a module and
its `declare module 'nuxt/schema'` block is a module augmentation — it only
takes effect once something pulls the file into the program. Nothing does in
an app that installs docus from npm, so every `AppConfig` field declared
there is silently missing, and the app falls back to the shapes generated
from `nuxt.schema.ts`.

Since 5.13.0 that breaks `nuxi typecheck` in any app extending the layer,
because `useSeo` reads `AppConfig['seo']['schema']` (#1433) and only
`app/types/index.d.ts` declares it:

  node_modules/docus/app/composables/useSeo.ts(37,53): error TS2339:
  Property 'schema' does not exist on type
  '{ title?: string; description?: string; }'

`index.d.ts` is already reachable — Nuxt writes a `/// <reference path>` to
it into the consumer's `.nuxt/nuxt.d.ts` — so importing the types file from
there is enough to make the augmentation apply.

Verified with a minimal app extending a packed build of the layer: both
errors disappear, `pnpm lint` and `pnpm typecheck` still pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TCgqQUpt4KBXi9U9ae5iq6
@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

@sisou is attempting to deploy a commit to the NuxtLabs Team on Vercel.

A member of the Team first needs to authorize it.

Comment thread layer/index.d.ts Outdated
@larbish
larbish merged commit 8c971cf into nuxt-content:main Sep 30, 2026
1 of 2 checks passed
@sisou
sisou deleted the fix/app-config-types-in-consumers branch September 30, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants