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

标签 typescript vue.js vuejs2

我已经阅读了类似问题的多个答案,但是大多数解决方案都是不正确的解决方法。我需要帮助解释/解决为什么在 this 的所有实例上发生错误:

Property 'x' does not exist on type 'Vue'

发生错误的组件(请注意,如果我删除计算属性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"]
}

包.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',
  },
};

垫片-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;
}

最佳答案

为组件上的 props 键入和设置默认值是一种很好的做法,特别是在 TypeScript 下。

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

默认情况下将 prop 设置为 false,错误应该消失。

关于typescript - 类型 'x' 上不存在属性 'Vue',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63646553/

相关文章:

typescript - 如何将 Twix (momentjs) 与 Typescript 结合使用

javascript - 根据对象响应显示复选框 Angular

angular - 无法在 Angular 6 中发布

javascript - 在 Vue 应用程序中,检测是否发生按键或鼠标单击

vue.js - 如何从VUE中的列表中删除项目?

vue.js - Vue 2 - ESLint + 标准 + Prettier

javascript - 异常 : Error: Uncaught (in promise): TypeError: Cannot read property '0' of null any suggestion please?

vue.js - 如何使用 flowtype 以外的 React$Element 类型键入 JSX?

webpack - Vuejs 模块未找到错误无法使用 webpack 解析 '@/components/error

javascript - Vue.js:使用带有 v-for 循环和 v-if 的动态创建的 v-model 来显示/隐藏元素