类型“ Vue”上不存在属性“ x”

时间:2020-08-29 11:40:06

标签: typescript vue.js vuejs2

我已经阅读了类似问题的多个答案,但是大多数解决方案都是不正确的解决方法。对于为什么在 this 的所有实例上出现此错误的原因,我希望获得帮助/解释/解决方案:

类型'Vue'上不存在属性'x'

发生这种情况的组件(请注意,如果我删除了计算的属性showModal,将不再有任何错误)

<template>
  <v-row justify="center">
    <v-dialog id="edit-cattle" v-model="showModal" persistent scrollable max-width="600px">
      <v-card>
        <v-card-title>
          <span class="headline">Edit Cattle</span>
        </v-card-title>
        <v-card-text>
          <v-form v-model="valid">
            <v-container>
              <v-select id="status" :items="statusOptions" label="Status" v-model="client.status"></v-select>
            </v-container>
          </v-form>
        </v-card-text>
      </v-card>
    </v-dialog>
  </v-row>
</template>

<script lang="ts">
import Vue from "vue";
import firebase, { firestore } from "firebase/app";
import constants from "../constants/constants";
import {
  Client,
  ClientLegalType,
  ClientStatus,
  Month,
  ClientBank,
  ClientBankAccountType
} from "../models/client.model";
import helpers from "../helpers/helpers";
import algoliasearch from "algoliasearch";

export default Vue.extend({
  name: "EditClient",
  props: {
    client: Object as () => Client,
    showModalValue: Boolean
  },
  data() {
    return {
      postalSameAsPhysical: false,
      valid: false,
      loading: false,
      registrationDate: (this.client
        ?.registrationDate as firebase.firestore.Timestamp)
        ?.toDate()
        .toISOString()
        .substr(0, 10),
      legalTypeOptions: Object.keys(ClientLegalType).map(value => {
        return { text: helpers.camelToWords(value), value: value };
      }),
      statusOptions: Object.keys(ClientStatus).map(value => {
        return { text: helpers.camelToWords(value), value: value };
      }),
      monthOptions: Object.keys(Month).map(value => {
        return { text: helpers.camelToWords(value), value: value };
      }),
      bankOptions: Object.keys(ClientBank).map(value => {
        return { text: helpers.camelToWords(value), value: value };
      }),
      bankAccountTypeOptions: Object.keys(ClientBankAccountType).map(value => {
        return { text: helpers.camelToWords(value), value: value };
      })
    };
  },
  methods: {
    passData() {
      const updatedClient: Client = {
        ...this.client //Property 'client' does not exist on type 'Vue'
      };
      //Property 'registrationDate' does not exist on type 'Vue'
      if (this.registrationDate) {
        updatedClient.registrationDate = firebase.firestore.Timestamp.fromDate(
          new Date(this.registrationDate)
        );
      }
      console.log("updatedClient: ", updatedClient);
      this.showModal = false; //Property 'showModal' does not exist on type 'Vue'.
      this.$emit("saveData", helpers.undefinedToNull(updatedClient));
    }
  },
  computed: {
    algoliaClient(): any {
      const client = algoliasearch(
        constants.ALGOLIA.APP_ID,
        constants.ALGOLIA.SEARCH_KEY
      );
      return client.initIndex(constants.ALGOLIA.INDEXES.CLIENTS);
    },
    showModal: {
      get(): Boolean {
        return this.showModalValue //Property 'showModalValue' does not exist on type '(() => any) | ComputedOptions<any>'.;
      },
      set(value) {
        this.$emit("updateShowModalValue", value); //Property '$emit' does not exist on type '(() => any) | ComputedOptions<any>'.
      }
    }
  },
});
</script>

我的配置文件:

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "noImplicitThis": false,
    "sourceMap": true,
    "baseUrl": ".",
    "types": ["webpack-env", "vuetify"],
    "paths": {
      "@/*": ["src/*"]
    },
    "lib": ["esnext", "dom", "dom.iterable", "scripthost"]
  },
  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx"],
  "exclude": ["node_modules"]
}

package.json

{
  "name": "xxx",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "algoliasearch": "^4.4.0",
    "core-js": "^3.6.5",
    "eslint-config-prettier": "^6.11.0",
    "firebase": "^7.19.1",
    "moment": "^2.27.0",
    "register-service-worker": "^1.7.1",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0",
    "vuetify": "^2.2.11",
    "vuex": "^3.4.0"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^2.33.0",
    "@typescript-eslint/parser": "^2.33.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-pwa": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^5.0.2",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-vue": "^6.2.2",
    "prettier": "^1.19.1",
    "sass": "^1.19.0",
    "sass-loader": "^8.0.0",
    "typescript": "~3.9.3",
    "vue-cli-plugin-vuetify": "~2.0.7",
    "vue-template-compiler": "^2.6.11",
    "vuetify-loader": "^1.3.0"
  }
}

eslintrc.js

module.exports = {
  root: true,
  env: {
    node: true,
  },
  extends: [
    'plugin:vue/essential',
    'eslint:recommended',
    '@vue/typescript/recommended',
    '@vue/prettier',
    '@vue/prettier/@typescript-eslint',
  ],
  parserOptions: {
    ecmaVersion: 2020,
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
  },
};

shims-tsx.d.ts

import Vue, { VNode } from "vue";

declare global {
  namespace JSX {
    // tslint:disable no-empty-interface
    interface Element extends VNode {}
    // tslint:disable no-empty-interface
    interface ElementClass extends Vue {}
    interface IntrinsicElements {
      [elem: string]: any;
    }
  }
}

shims-vue.d.ts

declare module "*.vue" {
  import Vue from "vue";
  export default Vue;
}

1 个答案:

答案 0 :(得分:0)

优良作法是输入和设置要添加到组件的道具的默认值,特别是在TypeScript下。

这里的问题是由于您对计算属性的类型定义,它期望返回false,但是showModalValue属性没有默认值。因此最初是undefined,未定义普通javascript是falsey,但不是在TypeScript中。

将属性默认设置为false,错误应该消失了。