vuejs / composition-api

Composition API plugin for Vue 2

Home Page:https://composition-api.vuejs.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unable to use component's method in TypeScript

0140454 opened this issue · comments

Environment

Packages

  • ts-loader v8.2.0
  • vue v2.6.14
  • @vue/composition-api v1.4.0

Shims

shims-vue.d.ts

declare module '*.vue' {
  import Vue from 'vue'
  export default Vue
}

Description

There is a ref in my template to call method defined in child component.

In setup(), I use child = ref<InstanceType<typeof ChildComponent>>() to declare it and use it in onMounted() callback function later.

However, ts-loader outputs the following errors while compiling:

ERROR in /project/src/pages/Demo.vue.ts
[tsl] ERROR in /project/src/pages/Demo.vue.ts(15,20)
      TS2339: Property 'work' does not exist on type 'CombinedVueInstance<Vue, object, object, object, Record<never, any>>'.

Is it possible that shims-vue.d.ts makes ts-loader not infer type correctly?

Example Code

ChildComponent.vue

<template>
  <div />
</template>

<script lang="ts">
import { defineComponent } from '@vue/composition-api'

export default defineComponent({
  name: 'Demo',
  setup() {
    const work = () => {
      console.log('work')
    }

    return { work }
  },
})
</script>

<style lang="scss" module></style>

Demo.vue

<template>
  <child-component ref="child" />
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from '@vue/composition-api'
import ChildComponent from './ChildComponent.vue'

export default defineComponent({
  name: 'Demo',
  setup() {
    const child = ref<InstanceType<typeof ChildComponent>>()

    onMounted(() => {
      child.value!.work()
    })

    return { child }
  },
})
</script>

<style lang="scss" module></style>

If I remove declare module '*.vue' in shims-vue.d.ts, vue-tsc will complain TS7016: Could not find a declaration file for module.
Therefore, I keep shims-vue.d.ts and continue item 2 and 3 you mentioned.

Since I use webpack4 and ts-loader now, I perform the following steps:

  1. Add transpileOnly: false in ts-loader options
  2. Follow Volar tutorial, add @vue/runtime-dom and set necessary options to avoid JSX errors in template block

Currently, vue-tsc is responsible for type checking, and webpack is for other works. In the meanwhile, IDE with Volar extension works great.

@xiaoxiangmoe Thanks for your help. But if there is wrong in the above steps, please continue giving me some advice.
Or, this issue can be closed.

Can you give me a repo for reproduction?

While making a repository for reproduction, I found that TS7016 error generated because included files are not written in TypeScript.

My project contains Vue components written in JavaScript or TypeScript.
Those files, who don't have script block or there is no lang="ts" in script tag, will make vue-tsc generate TS7016 error.

Repository: https://github.com/0140454/vue-test

Is it possible to use JavaScript and TypeScript at the same time? Just keep shims-vue.d.ts as now?

@0140454 add "allowJs": true, in tsconfig

After adding "allowJs": true in tsconfig, TS7016 gone.

However, if there is a event handler or variable in attribute, vue-tsc generate TS2304: Cannot find name error even though I have exposed them in setup().

This error is not generated when allowJs is false.

The repository has been updated for TS2304.

Sorry for confusion. But TS2304 errors are reported in ts .vue files.

The js .vue files seems to be fine to vue-tsc.

Maybe you should add types for js .vue files, or use defineComponent to wrap object.

@xiaoxiangmoe Thanks for your hint.

After I use Vue.extend to wrap object exported in js .vue file, it passes vue-tsc check.

why not use defineComponent?

Oh, sorry that I forget updating.

defineComponent and Vue.extend both can eliminate TS2304. I just try Vue.extend first, and I have changed it to defineComponent now.