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
    }
}
Giacomo
  • 1,056
  • 4
  • 16
  • 24
  • Your method return type / signature look different than in this example https://stackoverflow.com/a/44350932/3254405 and also first example uses function keyword may be try this way.. – boateng Oct 02 '18 at 13:55
  • I can remove the return type and the error doesn't go away – Giacomo Oct 02 '18 at 13:56
  • You could define an interface: https://github.com/vuejs/vue/issues/8406#issuecomment-419605178 – Bennett Dams Oct 02 '18 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 – Giacomo Oct 02 '18 at 14:01

1 Answers1

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[],
}
Ricky Ruiz
  • 25,455
  • 6
  • 44
  • 53
  • I fixed it with `itemsList: { type: Array } as PropOptions` 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) – Giacomo Oct 02 '18 at 17:13
  • 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. – Ricky Ruiz Oct 02 '18 at 18:08