搜索

首页  >  问答  >  正文

解决Vue3 Typescript中类型上不存在的属性问题

我正在尝试用来自 API 的线索填充组件。我有一个 LeadService 文件以及我的 vue 模板文件。我遇到的问题是,我在模板文件上使用异步调用,该调用有效,但是当我去计算值时,它会抛出 property does not exit on type 错误。它实际上有效,您可以看到错误消息后面的正确组件。我不知道如何让错误消失。

这里是服务类LeadService.ts

import ApiService from "@/core/services/ApiService";

interface Lead {
  id: string;
  first_name: string;
  last_name: string;
  lead_form_name: string;
  email: string;
  campaign: string;
  timestamp: number;
  mobile_number: string;
  message: string;
  medium: string;
  city: string;
  state: string;
  leadType: string;
  quality: string;
  source: string;
  call_link: string;
  company: string;
  country: string;
}

export default class LeadService {

  getLeads() {

    const accountInfo = JSON.parse(localStorage.getItem('accountInfo') || '{}');

    ApiService.setHeader();

    return ApiService.query("/leads", {params: {client_id : accountInfo.client_id}})
      .then(({ data }) => {
        let leadData: Lead[] = data['Items'];
        return leadData;
      })
      .catch(({ response }) => {
        return response;
      });

  }
}

这是我的 vue 模板 Leads.vue

<template>
  <!--begin::Leads-->
  <div class="row gy-5 g-xl-8 mb-8">
    <div class="col-xxl-12">
      <LeadTracker
        :lead-data="leadData"
        :updateQuality="updateQuality"
        :key="componentKey"
      />
    </div>
  </div>

  <div class="row gy-5 gx-xl-8 mb-8">
    <div class="col-xxl-8">
      <LeadMethods
        chart-height="500"
        :method-data="getLeadMethods"
      ></LeadMethods>
    </div>
  </div>
  <!--end::Leads-->
</template>

<script lang="ts">
import { defineComponent, onMounted } from "vue";
import { setCurrentPageTitle } from "@/core/helpers/breadcrumb";
import LeadMethods from "@/components/leads/methods/LeadMethods.vue";
import LeadTracker from "@/components/leads/tracker/LeadTracker.vue";
import LeadService from "@/core/services/LeadService";
import ApiService from "@/core/services/ApiService";

export default defineComponent({
  name: "leads",
  components: {
    LeadMethods,
    LeadTracker,
  },
  data() {
    return {
      leadData: {},
    }
  },
  beforeMount: async function() {
    this.leadData = await new LeadService().getLeads()
  },
  setup() {
    onMounted(() => {
      setCurrentPageTitle("Lead Activity");
    });

    const sourceThreshold = 5;

    return {
      sourceThreshold,
      componentKey: 0
    };
  },
  computed: {
    getLeadMethods(): object {
      const leadMethods: Array<object> = [];
      const totalLeads = this.leadData.length;

      console.log('called getLeadMethods check this.leadData', this.leadData);

      // Get the total number of Paid Media leads
      const totalPaid = this.leadData.filter(
        lead => lead.medium == "paid_media"
      ).length;

      // Get the total number of Calls
      const totalCall = this.leadData.filter(lead => lead.leadType == "call")
        .length;

      // Separate form leads from the rest
      const formData = this.leadData.filter(lead => lead.leadType == "form");

      // Make array for form names
      const formTypes: Array<string> = [];
      this.leadData.filter(lead => {
        if (!formTypes.includes(lead.lead_form_name))
          formTypes.push(lead.lead_form_name);
      });

      // Create objects for each form by name, push to leadMethods
      formTypes.filter(type => {
        let totalFormLeads = 1;
        formData.filter(form => {
          if (form.lead_form_name == type) totalFormLeads++;
        });
        const formMethod = {
          name: type,
          description: "Lorem ipsum dolor sit amet, consectetur.",
          total: totalFormLeads,
          percent: Math.round((totalFormLeads / totalLeads) * 100)
        };
        leadMethods.push(formMethod);
      });

      const callTracking = {
        name: "Location Based Call-Tracking",
        description: "Lorem ipsum dolor sit amet, consectetur.",
        total: totalCall,
        percent: Math.round((totalCall / totalLeads) * 100)
      };
      const paidSearch = {
        name: "Paid Search",
        description: "Lorem ipsum dolor sit amet, consectetur.",
        total: totalPaid,
        percent: Math.round((totalPaid / totalLeads) * 100)
      };

      leadMethods.push(callTracking, paidSearch);

      return leadMethods;
    }
  }
});
</script>

问题始于我的计算函数,我开始过滤 this.LeadData 基本上每个过滤器都会抛出 Property does not exit on type 错误,但它们确实存在。

需要注意的是,当 this.leadData 被设置时,它是一个代理。 任何帮助将不胜感激,我想知道是否可以抑制错误,尽管我不喜欢这个解决方案。

例如,在计算方法中的第一个过滤器中

// Get the total number of Paid Media leads
      const totalPaid = this.leadData.filter(
        lead => lead.medium == "paid_media"
      ).length;

mediumleadData 的一个属性,我实际上可以控制台记录它并且它工作得很好,但它仍然总是抛出 property does not exit on type

P粉336536706P粉336536706243 天前761

全部回复(1)我来回复

  • P粉111627787

    P粉1116277872024-03-26 11:33:46

    leadData 的类型是从 data() 中的声明推断出来的。它被初始化为 {},这意味着它的类型是一个不可变的空对象(并且不能附加任何属性)。但是,leadData 最终被分配了 LeadService().getLeads() 的返回值,所以它的类型实际上应该是 Lead 对象的数组。

    要正确输入 leadData,请使用 Lead[] 的类型断言:

    export default defineComponent({
      data() {
        return {
          //leadData: {}, ❌
          leadData: [] as Lead[], ✅
        }
      }
    })
    

    回复
    0
  • 取消回复