vue-next-webpack-preview icon indicating copy to clipboard operation
vue-next-webpack-preview copied to clipboard

Typescript support

Open ChrisShank opened this issue 5 years ago β€’ 16 comments

I am adding Typescript and I am not certain what the shim for *.vue files should be? My best guess is:

// shims-vue.d.ts
declare module '*.vue' {
  import { Component } from 'vue'
  const component: Component
  export default component
}

does anyone know if this is correct?

ChrisShank avatar Jan 04 '20 20:01 ChrisShank

Since *.vue files only export object-format components in v3, you can use ComponentOptions instead Component (the latter is a union type which includes FunctionalComponent)

yyx990803 avatar Jan 29 '20 15:01 yyx990803

@ChrisShank Do you have a working setup for Typescript? If so, would you be willing to share it? I struggled with including support for .ts files…

Timmitry avatar Feb 26 '20 19:02 Timmitry

Hi @Timmitry see my fork!

Edit : also added vue-router@next and vuex@next to my fork!

ChrisShank avatar Feb 28 '20 03:02 ChrisShank

@ChrisShank Thanks a lot, adding your changes worked like a charm πŸŽ‰ Now only vetur needs to remove the The template root requires exactly one element.-error, but I can ignore that πŸ˜‰

Timmitry avatar Feb 28 '20 07:02 Timmitry

How To Add JSX Support

bekalshenoy avatar Apr 25 '20 14:04 bekalshenoy

@ChrisShank Thanks for the fork, it is exactly what I was looking for!! :smile:

Idk if you saw this too but I was receiving this error in router.ts on your fork:

[tsl] ERROR in /home/.../src/router.ts(8,18)
      TS2322: Type 'new () => ComponentPublicInstance<{}, { store: any; }, {}, {}, {}, Record<string, any>, VNodeProps>' is not assignable to type 'undefined'.

But it seems to work fine if I change the routes to async functions like:

routes: [
  { path: '/', component: async () => Home, name: 'home' },
  { path: '/about', component: async () => About, name: 'about' },
],

onx2 avatar Apr 29 '20 00:04 onx2

@bekalshenoy JSX seems to be a work in progress right now... https://github.com/vuejs/vue-next#official-libraries-vue-3-support-status

ChrisShank avatar Apr 29 '20 00:04 ChrisShank

@onx2 Unfortunately I haven't been able to reproduce that error. I just updated the dependencies of my fork (most notably to [email protected]) so maybe that could fix it? Here is the commit. Let me know if there is anything else I can do! πŸ˜„

ChrisShank avatar Apr 29 '20 01:04 ChrisShank

@Timmitry here is a TS version of this repo. I did not use JSX, however. Just plain render functions. Just an idea. https://github.com/deemaxx/vue-next-webpack-typescript

deemaxx avatar May 07 '20 19:05 deemaxx

I get an error when I use a imported component as a type.

import { defineComponent, ref } from "vue"
import HelloWorld from "./components/HelloWorld.vue"

export default defineComponent({
  components: { HelloWorld },
  setup() {
    const componentRef = ref<HelloWorld | null>(null)
  }
})

'HelloWorld' refers to a value, but is being used as a type here.

janispritzkau avatar Jun 08 '20 12:06 janispritzkau

@janispritzkau HelloWorld is a value here. typeof HelloWorld will give you the type of that Vue component.

ChrisShank avatar Jun 08 '20 13:06 ChrisShank

I found a solution but it feels a bit like a hack.

const componentRef = ref<InstanceType<typeof HelloWorld> | null>(null)

@ChrisShank typeof only gives you the constructor type.

janispritzkau avatar Jun 08 '20 13:06 janispritzkau

I noticed that I was only able to directly use the components as a type because I was using class components.

I also ran into another problem that you can't self reference a component, or have a child component, that has a type reference of it's parent which has the child component defined in it's components.

janispritzkau avatar Jun 08 '20 17:06 janispritzkau

I almost got it working using the following approach:

<template>
  <hello-world ref="hello">
</template>

<script lang="ts">
import { ComponentOptions } from 'vue';
import HelloWorld from "./components/HelloWorld.vue"

// helper function to attach type to a vue reference
function typesafeComponentRef<T>(elementRef: Element, vueComponent: T) {
  type ExtractVueComponentType<X> = X extends ComponentOptions<any, infer Data, any, any, any, any> ? Data : never;
  return elementRef as ExtractVueComponentType<typeof vueComponent>;
}

export default defineComponent({
  setup(props, context) {
    watchEffect(() => {
      const helloWorld = typesafeComponentRef(context.refs.hello, HelloWorld)
      // here code completion works in Intellij
      // but the type of helloWorld is always `unknown`
      const x = helloWorld.someDataVariable // autocompleted someDataVariable
      ...
    });
  }
});
</script>

vsimko avatar Jun 19 '20 22:06 vsimko

@ChrisShank Thanks a lot, adding your changes worked like a charm πŸŽ‰ Now only vetur needs to remove the The template root requires exactly one element.-error, but I can ignore that πŸ˜‰

you can set this for vetur "vetur.validation.template": false see this https://github.com/vuejs/vetur/issues/1976

Also I create a project with vue3 and webpack, you can take a look here

way2ex avatar Jul 25 '20 05:07 way2ex

@ChrisShank Thanks a lot, adding your changes worked like a charm πŸŽ‰ Now only vetur needs to remove the The template root requires exactly one element.-error, but I can ignore that πŸ˜‰

you can set this for vetur "vetur.validation.template": false see this vuejs/vetur#1976

Also I create a project with vue3 and webpack, you can take a look here

thx for your link can you translate your comments in the webpack.config in english please ?

DrMabuse23 avatar Jul 27 '20 09:07 DrMabuse23