typescriptvue.jsvisual-studio-codevuejs3vite

Cannot find module or its corresponding type declarations for index.vue files


I modified my vite.config.ts so that it recognizes index.vue files as entry points.

import { fileURLToPath, URL } from 'node:url'

import vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    vue(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    },
    extensions: ['.js', '.ts', '.vue', '.json'] // added line
  },
  server: {
    port: 3000
  }
})

Thanks to this configuration, I can do this

import MyComponent from '@/components/MyComponent' // automatically imports index.vue

MyComponent folder looks like this

MyComponent
|
+---index.vue
|
+---Subcomponent1.vue
|
+---...

It works, index.vue is automatically imported. The only issue is that index.vue is not properly resolved. I'm getting following error: Cannot find module '../components/MyComponent' or its corresponding type declarations.ts-plugin(2307)

Due to this error I cannot navigate to index.vue when I try to go to the definition.

Edit #1

Thanks to Estus Flask insights I was able to find a solution which does not require changing many things, just create your folder like this

FencyComponent
|
+---FencyComponent.vue
|
+---Subcomponent1.vue
|
+---...

and then add a index.ts file which import and exports the main component, like this

// index.ts

import FencyComponent from './FencyComponent.vue'

export default FencyComponent

Now you can import it like this

import FencyComponent from '@/components/FencyComponent' // it's a folder

The IDE won't complain at all.


Solution

  • The problem may appear in a specific environment or tool (IDE). What you're trying to do is know to produce unreliable and undocumented behaviour, both resolving a folder to index file, and and omitting .vue extension. Also naming a component index.vue prevents a component from inferring correct name based on file name at compilation time, this should be preferably avoided .

    A trouble-free way to do this is to import a component as @/components/MyComponent/MyComponent.vue. It's possible to re-export a component in index.ts (also necessary if a folder needs to expose several components), but in this case this may require to import it as @/components/MyComponent/index for compatibility reasons.

    A more reliable way to import from @/components/MyComponent folder is to provide components/MyComponent/package.json that maps its contents through main, exports, etc package.json fields, this is the way it's done in third-party libraries like Primevue:

    {
      "main": "./MyComponent.vue",
      "module": "./MyComponent.vue"
    }
    

    This requires the explicit support from the tools and relies on the resolution of Node modules that is expected to be correctly implemented.

    The support for TypeScript types in IDEs (specifically VSCode) is limited by their implementation and can be improved by providing components/MyComponent/MyComponent.vue.d.ts dummy type file:

    export default import("./MyComponent.vue")