When using this inside the head() function of a component, this does not let you access computed

Esurnir
0
Esurnir
commented 6 months ago

Version

v2.14.4

Reproduction link

https://github.com/Esurnir/real-world-nuxt/tree/thistypingrepro

Steps to reproduce

Clone the repository.
Install dependencies with "yarn"
Run the server with yarn dev.
Check the _id.vue file in visual studio code with Vetur.

What is expected ?

No typescript error get emitted when running the server.
No typescript error in Vetur.

What is actually happening?

In the console output I get :
TS2339: Property 'id' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, unknown, Readonly<Record<never, any>>>'.
14 | head() {
15 | return {

16 | title: "Event #" + this.id,
| ^^
17 | meta: [
18 | {
19 | hid: "description",

in visual studio code I get "Property 'id' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, unknown, Readonly<Record<never, any>>>'.Vetur(2339)"

Additional comments?

I can go around it by using this.$route.params.id which is properly typed. I've already added type annotation to the id.
I can of course do (this as any).id but that defeats the purpose of the typings.

bug
0
Esurnir
0
Esurnir
commented 6 months ago

Sorry in advance if it's in the wrong repo for this issue. I couldn't find anything else that related to typescript support in the list of repository.

0
hmsk
2.2k
hmsk
commented 6 months ago

The shortest answer is "Give returning type MetaInfo for head() explicitly"

diff --git a/pages/options-api.vue b/pages/options-api.vue
index bcd4ae9..aa49224 100644
--- a/pages/options-api.vue
+++ b/pages/options-api.vue
@@ -45,6 +45,7 @@

 <script lang="ts">
 import Vue from 'vue'
 import { mapActions, mapState } from 'vuex'
+import { MetaInfo } from 'vue-meta'

 import type { RootState } from '~/store'
@@ -62,6 +63,7 @@ export default Vue.extend({
   middleware: 'user-agent',

   fetch () {
     return fetch('https://jsonplaceholder.typicode.com/todos')
       .then(response => response.json())
       .then((data: ToDo[]) => { this.fetchedTodos = data })
@@ -103,9 +105,9 @@ export default Vue.extend({
     })
   },

-  head () {
+  head (): MetaInfo {
     return {
-      title: 'Options API Demo'
+      title: this.message
     }
   }
 })

or explicitly type of this on head with head(this: MyComponentType).

Longer answer

TS infers component's properties on this from head() as similar as computed, data() during we don't give explicit returning type MetaInfo. However, that doesn't work as intended somehow. (I'm not familiar with how VueComponentOption works to share types on this)

I have tried to find a way to patch this problem by overwriting typedefs on @nuxt/types, but couldn't see a feasible solution.

@kevinmarrec may be an appropriate person who can grasp the reason why.

Ref

1
Esurnir
0
Esurnir
commented 6 months ago

Oh neat! Typing head solves all my problems.

Maybe this is a documentation issue ? (I went through a lot of google search and issues, and I couldn't find an answer)

0
hmsk
2.2k
hmsk
commented 6 months ago

This seems to be the issue of vue-meta, but I will demonstrate on the templates explicitly.

0
Informations
Bug ReportOpen
#c59 - Created 6 months ago