You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VueJS 2 + TypeScript下computed无法识别data定义属性的类型报错问题

问题复现

如下组件代码:

<template lang="html">
  <div>
    <p>{{ bar }}</p>
  </div>
</template>

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

export const FooBar = Vue.extend({
  computed: {
    bar: function() {
      return this.foo;
    }
  },
  data: function() {
    return {
      foo: 'bar',
    };
  },
});

export default FooBar;
</script>

触发TypeScript错误:

13:19 Property 'foo' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, unknown, Readonly<Record<never, any>>>'.
    11 |   computed: {
    12 |     bar: function() {
  > 13 |       return this.foo;
       |                   ^
    14 |     }
    15 |   },
    16 |   data: function() {
Version: typescript 4.1.6

错误原因

该报错是Vue 2 中Vue.extend的类型推导能力限制导致的:TypeScript 无法自动识别未按推导顺序声明的组件选项类型,当computed写在data之前时,TS 尚未完成对data返回值的类型推导,就会判定this上不存在foo属性。


可行解决方案(无需使用类式组件语法)

  • 方案1:调整组件选项书写顺序
    将data选项移到computed等其他选项之前,让TS优先推导data类型,即可自动完成后续类型识别,修改后代码如下:
<template lang="html">
  <div>
    <p>{{ bar }}</p>
  </div>
</template>

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

export const FooBar = Vue.extend({
  data: function() {
    return {
      foo: 'bar',
    };
  },
  computed: {
    bar: function() {
      return this.foo;
    }
  },
});

export default FooBar;
</script>
  • 方案2:显式声明泛型参数
    如果需要保留原有选项顺序,可以手动给Vue.extend传入泛型参数,声明组件的各类选项类型,写法如下:
import Vue from 'vue';

// 声明data类型
interface ComponentData {
  foo: string
}
// 声明computed类型
interface ComponentComputed {
  bar: string
}

// 泛型参数顺序:Data、Methods、Computed、Props、基础Vue实例类型
export const FooBar = Vue.extend<ComponentData, unknown, ComponentComputed, unknown>({
  computed: {
    bar: function() {
      return this.foo;
    }
  },
  data: function() {
    return {
      foo: 'bar',
    };
  },
});

export default FooBar;
  • 方案3:使用defineComponent
    Vue 3 内置的defineComponentAPI 优化了Options API的类型推导能力,无需调整选项顺序即可自动识别所有属性。如果是Vue 2项目,可以安装vue-demi包适配使用defineComponent,Vue3项目直接使用即可:
import { defineComponent } from 'vue';

export const FooBar = defineComponent({
  computed: {
    bar() {
      return this.foo;
    }
  },
  data() {
    return {
      foo: 'bar',
    };
  },
});

export default FooBar;
  • 方案4:使用Composition API写法
    Composition API天然对TypeScript支持友好,类型推导更直观,无需处理this的类型问题。Vue2项目可安装@vue/composition-api包使用,Vue3内置支持:
import { defineComponent, ref, computed } from 'vue';

export default defineComponent({
  setup() {
    const foo = ref('bar');
    const bar = computed(() => foo.value);
    return {
      foo,
      bar
    }
  }
})

内容的提问来源于stack exchange,提问作者David Roussov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 14:36:01