Generate type definitions for Vue components (and props) built with Vite

Viewed 40

I scaffolded a new vue 3 project using the CLI tool and it also installed Vite which I'm fine with. My goal was to develop a component library in vue, so I can use it in other projects. I wanted to have proper code completion for those components just like Vuetify for example has.

From what I saw, Vite can't create type definitions on it's own, so I tried out different plugins like the typescript plugin as well as others mentioned in this GitHub issue.

This is the vite config I am using to build my library (using vite-plugin-dts):

export default defineConfig({
  plugins: [
    vue(),
    dts({
      insertTypesEntry: true,
    }),
  ],
  build: {
    emptyOutDir: true,
    outDir: 'dist/lib',
    lib: {
      entry: path.resolve(__dirname, 'src/components.ts'),
      name: 'testComponents',
      fileName: (format) => `components.${format}.js`
    },
    rollupOptions: {
      external: ['vue', 'vuetify'],
      output: {
        globals: {
          vue: 'Vue',
          vuetify: 'Vuetify'
        }
      }
    }
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
})

In my entry file I'm simply importing all vue components and exporting them again:

import Map from './components/map/SimpleMapbox.vue'
import KpiBox from './components/kpi/KpiBox.vue'
import SideNav from './components/layout/SideNav.vue'
import TopNav from './components/layout/TopNav.vue'
import ButtonGroup from './components/forms/ButtonGroup.vue'

import * as types from './types'

export { Map, KpiBox, SideNav, TopNav, ButtonGroup, types }

And according to most tutorials I added the paths to the generated umd and es files to the files, module, main and exports properties in the package.json.

The plugin generated an index.d.ts with named exports, but it created a vue.d.ts file for only one of the components for some reason:

<script setup lang="ts">
import { useTheme } from 'vuetify'
import { ref } from 'vue'
import { mdiBrightness5, mdiInformationOutline, mdiCog, mdiBrightness2 } from '@mdi/js'

defineEmits(['click:burger', 'click:info', 'click:settings'])
const theme = useTheme()
const themeSwitch = ref(false)

function toggleTheme() {
  theme.global.name.value = theme.global.current.value.dark ? 'lightMode' : 'darkMode'
}

defineProps({
  title: { type: String, default: 'My Components' },
  height: { type: String, default: '64' },
  avatar: { type: String, default: 'https://icon-library.com/images/default-profile-icon/default-profile-icon-24.jpg' },
  username: { type: String, default: '' }
})
</script>

Anyone has an idea why it only generated prop definitions for one component? All my components are using the script with the setup attribute syntax, there's no difference or whatsoever...

0 Answers
Related