How to handle type errors when using properties in Vue3 Single File Components with TypeScript

I've hit a roadblock while attempting to utilize properties in Vue3. Despite trying various methods, I keep facing issues during the type-check phase (e.g.: yarn build).

The project I'm working on is a fresh Vue3-ts project created using Vite. Below is an example of my component:

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  name: "Test",
  props: {
    label: {
      type: String as PropType<string>,
      required: true,
    },
  },
  methods:  {
    onClick() {
      console.log(this.label);  // This line triggers an error!
    },
  },
});
</script>

I receive an error stating that this.label does not exist:

Property 'label' does not exist on type 'CreateComponentPublicInstance<Readonly<ExtractPropTypes<Readonly<ComponentPropsOptions<Data>>>> & ...

(volar raises a similar issue).

I've experimented with different approaches but haven't had any success, including:


Utilizing the <script setup> method to define props:

<script setup lang="ts">
const props = defineProps({
  classes: String,
  label: String,
})
</script>

This also gives a warning about the unused props variable. Although this isn't major, the initial error persists.


Implementing a setup method within my component:

  setup(props) {

    defineProps({
      classes: String,
      label: String,
    })
  },

Adopting the traditional way of defining props with overzealous type declarations:

export default defineComponent({
  name: "AppStory",
  props: {
    label: {
      type: String as PropType<string>,
      required: true,
    },
  },

A more conservative approach with type definitions:

export default defineComponent({
  name: "AppStory",
  props: {
    label: {
      type: String,
      required: true,
    },
  },

Does anyone have a successfully functioning Single File Component (SFC) in Vue3 that effectively utilizes properties? What am I missing here? Most examples I come across either lack props or don't incorporate TypeScript. The documentation for Vue3 doesn't focus much on TypeScript, and the examples provided do not seem to address this rather fundamental scenario.

Answer №1

I recently set up a new vite application using the vue-ts configuration, and I noticed that in the initial example, the only thing missing is the import of the `PropType` type.

<template>
  <div>
    <button @click="onClick">{{ label }}</button>
  </div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue";

export default defineComponent({
  name: "Test",
  props: {
    label: {
      type: String as PropType<string>,
      required: true,
    },
  },
  methods: {
    onClick() {
      console.log(this.label); // This line yields an error!
    },
  },
});
</script>

Here is the parent component (default App.vue component)

<script setup lang="ts">
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
import HelloWorld from "./components/HelloWorld.vue";
</script>

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld label="Hello Vue 3 + TypeScript + Vite" />
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Everything seems to be working well for me.

Now, let's take a look at the same example using the 'setup' keyword in the script tag:

<template>
  <div>
    <button @click="onClick">{{ label }}</button>
  </div>
</template>

<script lang="ts" setup>
import { PropType } from "vue";
const props = defineProps({
  label: {
    type: String as PropType<string>,
    required: true,
  },
});

const onClick = () => {
  console.log(props.label); // This line yields an error!
};
</script>

This setup also works without any issues.

Lastly, let's see how it looks when using the 'setup' method:

<template>
  <div>
    <button @click="onClick">{{ label }}</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from "vue";

export default defineComponent({
  name: "Test",
  props: {
    label: {
      type: String as PropType<string>,
      required: true,
    },
  },
  setup(props) {
    const onClick = () => {
      console.log(props.label); // This line yields an error!
    };
    return { onClick };
  },
});
</script>

Hoping this information helps resolve your issue.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A more concise validation function for mandatory fields

When working on an HTML application with TypeScript, I encountered a situation where I needed to build an error message for a form that had several required fields. In my TypeScript file, I created a function called hasErrors() which checks each field and ...

Angular asynchronous operations are failing to complete within the specified time frame

Observations suggest that Angular's async from @angular/core/testing is not properly resolving timeouts in tests when a beforeEach contains async as well. Sadly, the bug cannot be replicated on Plunkr or JSFiddle platforms. To reproduce this issue ea ...

The slides in Swiperjs are having trouble moving smoothly

I am experiencing some challenges with swiperjs where the slides are not snapping to the next slide and I am unable to fetch the active index from them. Below is a snippet of my code where I am using typescript, swiperjs version 6.84, and the Ionic frame ...

After running a npm run build command and hosting it on nodejs express.static, I attempted to start the app using pm2. However, I encountered an issue when trying to

I needed to set up hosting for 2 different node apps on a single Linux box from AWS EC2. I wanted to create a development environment and a staging environment, each using its own port. However, the issue I am currently facing is not related to port confli ...

Odd behavior of escape characters in Typescript

Looking for help with a query similar to the one referenced here. I am new to TypeScript and front end development. Currently using an Angular form to collect user input, which may contain regex. For example: The input from the form, stored in this.expr ...

Unable to fetch data from URL in Angular using the HttpClientModule

I have a goal in my application to retrieve data from the following URL and showcase it within the app: https://jsonplaceholder.typicode.com/posts/1 The issue I'm encountering is that the data is not being displayed in my app. The console is showing ...

Assessing the invalidity of user-defined type guards within class implementations

I just wrote this Typescript code and tested it in a sandbox. Check out the code snippet below: class Foo { public get test() : string|number{ return "foo" } public hasString() : this is { test:string }{ return type ...

What's the deal with the Zod getter function?

Is it possible to create a getter function within a Zod object? For instance, in ES5 you can achieve the following: const person = { firstName: "John", lastName: "Doe", get fullName() {return `${this.firstName} ${this.lastName}`} } person.fullNam ...

What are the recommended TypeScript tsconfig configurations for running Node.js 10?

Can someone provide information on the necessary target/libs for enabling Node.js v10.x to utilize async/await without generators? I have found plenty of resources for node 8 but not as much for node 10. ...

Can someone explain how to create a Function type in Typescript that enforces specific parameters?

Encountering an issue with combineReducers not being strict enough raises uncertainty about how to approach it: interface Action { type: any; } type Reducer<S> = (state: S, action: Action) => S; const reducer: Reducer<string> = (state: ...

Finding the IP address of a server in Angular: A Comprehensive Guide

Is there a way to dynamically retrieve the server host IP address in an Angular application launched with ng serve --host 0.0.0.0? This IP address will be necessary for communication with the backend server. As each coworker has their own unique IP addres ...

Encountered an issue with ionViewDidLoad: The property 'firstChild' cannot be read as it is null

While working on an Ionic 2 App with Angular2 and Typescript, I encountered an issue when trying to pass a JSON to map for markers. Here is the link to the gist containing the code snippet I am facing an error that reads: view-controller.js:231 MapPage i ...

Angular 4: Retrieving the selected element's object from a collection of elements

In my x.component.html file, I have a list of objects that are being displayed in Bootstrap cards like this: <div *ngFor="let item of items | async"> <div class="row"> <div class="col-lg-6"> <div class="card ...

Advantages of incorporating lazy loading in a Vue Single Page Application:

What level of realistic benefit can be expected from lazy loading in a Vue application using Vue-router, Vuex, and many components to improve initial load times in an SPA? In comparison to minifying and bundling code (in this case, with gulp), do the perf ...

The challenges of deploying a Vue.js frontend with a Flask backend on Heroku

My current project involves a Vue.js frontend with a Flask backend as the REST API. The code is structured in client and server folders within my Github repository. I am attempting to deploy this web app on Heroku using the Github deployment feature, but e ...

Is it possible to create diagrams using Vue.js?

Is there a way to create a diagram on the web and then render it as a json string? I'm looking for an npm plugin or any other idea that might help with this. Any suggestions? ...

Resolve ESLint errors in _document.tsx file of next.js caused by Document<any> and ctx.renderPage = () with TypeScript usage

maxbause took the initiative to create a comprehensive boilerplate project for Next.js, complete with GraphQL and styled components in TypeScript. Check out the project here However, upon integrating ESLint into the project, I encountered several warning ...

Exploring the possibilities of accessing Vue.prototype within an .addEventListener function

I've been attempting to access the global object Vue.prototype.$firebase, which is declared in main.js. import Vue from "vue"; import App from "./App.vue"; import router from "./router"; import VueTailwind from "vue- ...

Using Vue.js to pass a variable from a parent component to a child component

Parent component: ShowComment Child component: EditComment I'm attempting to pass the value stored in this.CommentRecID to the child component. In the template of ShowComment, I have included: <EditComment CommentRecID="this.CommentRecID" v-if= ...

Implementing Asynchronous context tracking within a Remix application utilizing Express as the server

Utilizing Remix with Express as the server, I aim to develop an Express middleware that establishes an async context to grant all downstream functions (especially those in the "backend" Remix code) access to this context within the scope of a single reques ...