9

I have the below Vue component:

<template>
    <v-snackbar bottom :color="color" v-model="snackbar">
        {{ msg }}
        <v-btn flat @click.native="close()">Close</v-btn>
    </v-snackbar>
</template>

<script lang="ts">
    import Vue from 'vue';
    import VueEvent from '../../VueEvent';

    export default Vue.extend({
        data(): object {
            return {
                snackbar: false,
                msg: '',
                color: '',
            };
        },
        created() {
            VueEvent.listen('snackbar', (data) => {
                this.snackbar = true;
                this.msg = data.msg;
                this.color = data.color;
            });
            this.malert();
        },
        methods: {
            close(): void {
                this.snackbar = false;
            }
        }
    });
</script>

<style scoped>

</style>

When Typescript compiles I get the following error:

Property 'snackbar' does not exist on type 'CombinedVueInstance<Vue, object, { close(): void; }, {}, Readonly<Record<never, any>>>'.
    28 |         methods: {
    29 |             close(): void {
  > 30 |                 this.snackbar = false;
       |                      ^
    31 |             }
    32 |         }
    33 |     });

Does anyone know how I can solve this problem, or explain why its happening?

3
  • Can you declare close(): void as an arrow function? Commented Jun 12, 2018 at 6:19
  • I get even more errors then. I can resolve it by doing (this as any).snackbar but it should work. I have looked at so many examples where this is how its done. I am also using the shim as stated in docs Commented Jun 12, 2018 at 6:43
  • Maybe it will help stackoverflow.com/questions/56002310/…. Commented Jul 23, 2021 at 21:46

1 Answer 1

4

Well, I don't have a good answer for you, but I have theory:

The original type declaration resides in vue/types/options.d.ts:

type DefaultData<V> =  object | ((this: V) => object); // here is the kicker
Data=DefaultData<V>
data?: Data;

And I found that:

data():object { ... // this.snackbar does not exist
data(){ ... // this.snackbar does exist.
data(): any { ... // this.snackbar does exist.
data(): { snackbar: boolean; msg: string; color: string } { ... // Also valid

I think without your object declaration typescript will think that data is DefaultData<V> = object. But once you say it returns an object, data will suddenly match ((this: V) => object) instead. Now typescript expects this to be of type V (which I assume is a vue-instance) and since that vue instance does not have a snackbar in it's definition, boom, typescript throws.

Lot's of guessing here, but I think pretty much anything except explicitly returning object would work to not match that second signature in DefaultData<V>.

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

1 Comment

This solved it, I guess i should really create an interface for my data? Anyway, problem solved, thanks

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.