Subscribe on changes!

@vue/compat not working with Typescript

avatar
Aug 13th 2021

Version

3.2.2

Reproduction link

https://github.com/philippevezina/vue-compat-ts

Steps to reproduce

  1. Spin up a new project with Vue CLI on Vue 2 with Typescript
  2. Upgrade "vue" to "^3.1.0"
  3. Add "@vue/compat": "^3.1.0"
  4. Replace "vue-template-compile" by "@vue/compiler-sfc": "^3.1.0"
  5. Configure vue.config.js as such:
// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.resolve.alias.set('vue', '@vue/compat')

    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(options => {
        return {
          ...options,
          compilerOptions: {
            compatConfig: {
              MODE: 2
            }
          }
        }
      })
  }
}
  1. Run yarn serve

What is expected?

The project should run on Vue 3 with Typescript with Vue 2 code.

What is actually happening?

Many errors for things that should be supported by @vue/compat such as this one:

ERROR in src/main.ts:6:5
TS2351: This expression is not constructable.
  Type 'typeof import("/Users/philippevezina/Documents/test/node_modules/vue/dist/vue")' has no construct signatures.
    4 | Vue.config.productionTip = false
    5 |
  > 6 | new Vue({
      |     ^^^
    7 |   render: h => h(App),
    8 | }).$mount('#app')
    9 |
avatar
Aug 13th 2021

I've also tried by adding the following in tsconfig.json and it did not work:

"paths": {
  "vue/*": [
     "@vue/compat/*"
  ]
}

and

"paths": {
  "vue/*": [
     "node_modules/@vue/compat/*"
  ]
}
avatar
Aug 13th 2021

You need to use createApp(). Are you following https://v3.vuejs.org/guide/migration/migration-build.html#installation with the example commits? https://github.com/vuejs/vue-hackernews-2.0/compare/migration.

Maybe it's worth adding more info in the docs repo. If you think so, a PR would be welcome 🙂

avatar
Aug 13th 2021

@posva

  • compat does provide a default export for a Vue 2 constructor.
  • The Migration guide also has migration to createApp() in step 7 of the install guide, while the app should run in step 5 already, where the codebase should still have new Vue(), I think it's reasonable to expect that TS should can deal with this.
  • especially since the constructor also has types:

https://github.com/vuejs/vue-next/blob/7ffa225aa334f0fd7da6ba30bee9109de3597643/packages/runtime-core/src/compat/global.ts#L67

But the default export doesn't seem to be properly typed with this. You can in fact do this in the prodived repo:

import { Vue, CompatVue } from 'vue'

(Vue as unkown as CompatVue).config.productionTip = false

Which would get rid of the error and instead shows helpful deprecation notes from the above type definition. but surely isn't the workflow we have in mind.

I first thought it might be an issue with the shims in that repo, but changing them to vue 3 style shims didnt't solve the issue.

I will reopen this as I think it should be possible to type the constructor properly.

avatar
Aug 13th 2021

It indeed seems to be a problem with the constructor typing. That being said, the workaround does not seem to be working on my end:

ERROR in src/main.ts:1:10
TS2305: Module '"../node_modules/vue/dist/vue"' has no exported member 'Vue'.
  > 1 | import { Vue, VueCompat } from 'vue'
      |          ^^^
    2 | import App from './App.vue'
    3 |
    4 | (Vue as unknown as VueCompat).config.productionTip = false

ERROR in src/main.ts:1:15
TS2305: Module '"../node_modules/vue/dist/vue"' has no exported member 'VueCompat'.
  > 1 | import { Vue, VueCompat } from 'vue'
      |               ^^^^^^^^^
    2 | import App from './App.vue'
    3 |
    4 | (Vue as unknown as VueCompat).config.productionTip = false
avatar
Aug 13th 2021

...which is why I directly deleted my comment again, seems you were faster though.

For one, the type is CompatVue, but the real problem was that i couldn't figure out how to augment the module without killing all the other types vue exposes.

avatar
Aug 13th 2021

Ohh my bad! This workaround, though not ideal, does indeed work:

import Vue, { CompatVue } from 'vue'

(Vue as unknown as CompatVue).config.productionTip = false
avatar
Sep 7th 2021

Here's how to get the types working (add this in a shim.d.ts):

declare module 'vue' {
  import { CompatVue } from '@vue/runtime-dom'
  const Vue: CompatVue
  export default Vue
  export * from '@vue/runtime-dom'
}

Also added to docs

avatar
Sep 8th 2021

Ohh great! Thanks!

avatar
Sep 21st 2023

Here's how to get the types working (add this in a shim.d.ts):

declare module 'vue' {
  import { CompatVue } from '@vue/runtime-dom'
  const Vue: CompatVue
  export default Vue
  export * from '@vue/runtime-dom'
}

Also added to docs

After I try this code, other members such as createApp do not exist. It is recommended to add

import Vue from 'vue'; // this add 
declare module 'vue' {
  import { CompatVue } from '@vue/runtime-dom'
  const Vue: CompatVue
  export default Vue
  export * from '@vue/runtime-dom'
}