0

I'm quite stuck trying to use properties with Vue3. I've tried a few different approaches, but all of them fail the type-check phase (e.g.: yarn build).

My project is a brand new vue3-ts project created using Vite. This is 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 yields an error!
    },
  },
});
</script>

I get an error that this.label does not exist: Property 'label' does not exist on type 'CreateComponentPublicInstance<Readonly<ExtractPropTypes<Readonly<ComponentPropsOptions<Data>>>> & ...

(volar complains about the same thing).

I've tried a few different approaches with no better luck, these are:


Using the <script setup> approach defining props:

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

This also warns about the unused props variable. That's not a big deal, but the above error is still there.


Using a setup method on my component:

  setup(props) {

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

Using the old-school form of defining props, a bit overzealous with defining types:

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

A slightly less zealous approach with the types:

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

Does anyone have a working example of SFC with Vue3 that use properties? What am I doing wrong? All the examples I'm finding out there have no props, or don't use TS. Vue'3 docs aren't very TS-centric, and no examples seem to cover this (rather basic) scenario.

1 Answer 1

1

well I created a new vite application using the vue-ts setup by default, and the only thing you're missing in the first example 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>

And this 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>

This is working fine for me.

Now the same example with 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>

It also works.

And finally 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>

Hopefully, this will solve your issue.

Sign up to request clarification or add additional context in comments.

3 Comments

I missed the import for PropType when copy-pasting samples around, but I do have it. Your examples fail to build for me with: paste.sr.ht/~whynothugo/… I installed storybook into my sample environment, maybe that's messing up, I'll try again.
Yup, merely running npx sb init on the environment messes up dependencies in a way that the project no longer builds. Thanks for the reply, I wouldn't have figured this out without your feedback.
Nice to know it, welcome!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.