Skip to content

Missing type hints and broken autocompletion after using hook to add custom scripts #580

@markmybytes

Description

@markmybytes

🐛 The bug

To add custom scripts to the project, I have followed the instruction in the documentation:

  1. Create a composable that implements steps to load the script and add types for its APIs
  2. Register a hook to add a custom script to the script registry in nuxt.config.

Howerver, after registering the hook, type hint for all useScript (both built-in and custom) composables become the type UseScriptContext<UseFunctionType<any, T>>, which cause the lost of APIs autocompletion for properties of the composable (e.g. .proxy, .onLoaded).

Behavior

Scenario 1 - Without Hook Registration

a. Initiatize the script in templates (or app.vue)

<script lang="ts" setup>
const foo = useScriptFoo({ id: 'GTM-ABCDEFG', debug: false });
</script>

Type hint work as expected on all script composables

b. Initiatize the script in nuxt.config

export default defineNuxtConfig({
  modules: ['@nuxt/scripts'],
  compatibilityDate: '2025-07-15',
  scripts: {
    registry: {
      foo: {
        id: 'GTM-ABCDEFG',
      },
    },
  },
});
<script lang="ts" setup>
const foo = useScriptFoo();
</script>

Entering the configuration for the custom script in nuxt.config without registering the hook, will result in a error with message "foo is not defined" on every page visit.

Scenario 2 - With Hook Registration

export default defineNuxtConfig({
  modules: ['@nuxt/scripts'],
  compatibilityDate: '2025-07-15',
  hooks: {
    'scripts:registry': function (registry) {
      registry.push({
        category: 'custom',
        label: 'My Custom Analytics',
        import: {
          name: 'useScriptFoo',
          from: resolve('./app/composables/useScriptFoo'),
        },
      });
    },
  },
});

By registering a hook on scripts:registry , and append the custom script into the script registry, both initialization method work as expected. No errors on page visits, scripts are properly loaded. However, autocompletion on all script composables are gone.

Image

For the GTM script (built-in script), type of the useScriptGoogleTagManager changed from UseScriptContext<GoogleTagManagerApi> to UseScriptContext<UseFunctionType<any, T>>, and no autocompletion its properties.

Image

For the custom script, type of the useScriptFoo changed from UseScriptContext<globalThis.FooAPI> to UseScriptContext<UseFunctionType<any, T>>, and no autocompletion for its properties.

Investigation

Upon further study, I found that when a script is pushed to the script registry via registry.push on scripts:registry hook, export {} will be deleted in .nuxt/module/nuxt-scripts.d.ts.

// .nuxt/module/nuxt-scripts.d.ts

declare module '#app' {
  interface NuxtApp {
-    $scripts: Record<string, (import('#nuxt-scripts/types').UseScriptContext<any>)>
+    $scripts: Record<'foo' | string, (import('#nuxt-scripts/types').UseScriptContext<any>)>
    _scripts: Record<string, (import('#nuxt-scripts/types').UseScriptContext<any>)>
  }
  interface RuntimeNuxtHooks {
    'scripts:updated': (ctx: { scripts: Record<string, (import('#nuxt-scripts/types').UseScriptContext<any>)> }) => void | Promise<void>
  }
}

+ declare module '#nuxt-scripts/types' {
+     type NuxtUseScriptOptions = Omit<import('../../runtime/types').NuxtUseScriptOptions, 'use' | 'beforeInit'>
+     interface ScriptRegistry {
+         foo?: import('/home/projects/nuxt-starter-7pu8bmxc/app/composables/useScriptFoo').FooInput | [import('/home/projects/nuxt-starter-7pu8bmxc/app/composables/useScriptFoo').FooInput, NuxtUseScriptOptions]
+     }
+ }

- export {}

If I add back export {} manualy, type hint and autocompletion for script composables will work properly again.

🛠️ To reproduce

https://stackblitz.com/edit/nuxt-starter-7pu8bmxc

🌈 Expected behavior

Type hint and autocompletion for script composable should work properly even if custom scripts are added using registry.push on scripts:registry hook.

ℹ️ Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions