2

I have this weird error that makes no sense. It's saying that isGenre does not exist on the type Vue, but ìsGenreis actually a computed property

<script lang="ts">
import Vue from 'vue'

import { WIDTH_TWO_ICONS } from '@/const/tables-style'

export default Vue.extend({
    props: {
        list: Array,
        listType: String
    },
    data: () => ({ WIDTH_TWO_ICONS }),
    computed: {
        isGenre(): boolean {
            return this.listType === 'genre'
        },
        isMood(): boolean {
            return this.listType === 'mood'
        }
    },
    methods: {
        routerLink(paramsId: number): object {
            return { name: 'GenreOrMoodEdit', params: { id: paramsId }, query: { type: this.isGenre ? 'genre' : 'mood' } }
        }
    }
})
</script>

Error

59:93 Property 'isGenre' does not exist on type 'Vue'.
    57 |     methods: {
    58 |         routerLink(paramsId: number): object {
  > 59 |             return { name: 'GenreOrMoodEdit', params: { id: paramsId }, query: { type: this.isGenre ? 'genre' : 'mood' } }
       |                                                                                             ^
    60 |         }
    61 |     }
    62 | })

Main.ts

declare module 'vue/types/vue' {
    // Global properties can be declared
    // on the `VueConstructor` interface
    interface VueConstructor {
        $axios: any
        router: any
    }
    interface Vue {
        $axios: any
        router: any
    }
}

import Vue from 'vue'
import App from './App.vue'
import router from '@/router'
import store from '@/store'
import './registerServiceWorker'
import '@/plugins'
import '@/directives'

import '@/sass/main.sass'

Vue.config.productionTip = false

new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')

Tsconfig.js

{
    "compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "strict": true,
        "jsx": "preserve",
        "importHelpers": true,
        "moduleResolution": "node",
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "sourceMap": true,
        "strictNullChecks": false,
        "baseUrl": ".",
        "types": ["node", "mocha", "chai"],
        "paths": {
            "@/*": ["src/*"]
        },
        "lib": ["esnext", "dom", "dom.iterable", "scripthost"]
    },
    "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx"],
    "exclude": ["node_modules"],
    "files": ["src/interfaces/*"]
}

Tslint.js

{
    "defaultSeverity": "warning",
    "extends": ["tslint:recommended"],
    "linterOptions": {
        "exclude": ["node_modules/**", "./src/assets/icons/*"]
    },
    "rules": {
        "quotemark": [true, "single", "avoid-escape"],
        "arrow-parens": false,
        "semicolon": false,
        "object-literal-sort-keys": false,
        "max-line-length": [true, 160],
        "ordered-imports": false,
        "interface-name": false,
        "trailing-comma": false,
        "no-unused-expression": true,
        "object-literal-shorthand": false,
        "curly": false,
        "no-console": false
    }
}
4
  • Your method return type / signature look different than in this example stackoverflow.com/a/44350932/3254405 and also first example uses function keyword may be try this way.. Commented Oct 2, 2018 at 13:55
  • I can remove the return type and the error doesn't go away Commented Oct 2, 2018 at 13:56
  • You could define an interface: github.com/vuejs/vue/issues/8406#issuecomment-419605178 Commented Oct 2, 2018 at 13:57
  • I find it very unnecessary, I should be able to access computed properties without having to define interfaces for each of them.. In fact I can access computed properties without problems elsewhere in the code Commented Oct 2, 2018 at 14:01

1 Answer 1

1

The problem is that you are defining your list prop as an Array.

Array is an alias for ArrayConstructor type.

arrayconstructor

The constructor of ArrayConstructor returns Array<any>, which is different from ArrayConstructor.

Workaround:

Create an interface for the list property.

ie.

list will be an array of Item.

interface Item { ... }

Cast the Array to a function that returns the interface.

props: {
  list: Array as () => Item[],
}
Sign up to request clarification or add additional context in comments.

2 Comments

I fixed it with itemsList: { type: Array } as PropOptions<IGenre[] | IMood[]> and it seems to have fixed the problem although I still don't understand it, since the computed was referencing the other props, and not "list" (or not itemsList)
Sadly, even though the computed property is not using the list prop it breaks. Just make sure to cast any prop which type is an Array. If I am not mistaken, there is a PR that exposes Prop instead of PropOptions to fix this issue, but it has not been merged. Hopefully with Vue 3, which will be fully written in TypeScript, these kind of things will get more attention.

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.