vue-class-component : TS2339 调用类方法时



我正在使用 vue-cli-service 来构建我的 vuejs 应用程序。

构建成功,但在 webstorm IDE 中,我收到一些 TS2339 错误:

Test.vue:

<template>
<div>{{method()}}</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class Test extends Vue {
public method(): string {
return 'hello';
}
}
</script>

测试规范:

import 'jest';
import {mount} from '@vue/test-utils';
import Test from '@/views/common/Test.vue';
describe('Test.vue', () => {
let wrapper: any;
beforeEach(() => {
wrapper = mount(Test);
});
test('test method call', () => {
const test = wrapper.find(Test).vm as Test;
expect(test.method()).toEqual('hello');
});
});

在Test.spec.ts中,我在编辑器和打字稿窗口中都收到此错误:

错误:(14, 21) TS2339:类型"Vue"上不存在属性"方法"。

但是测试是正常的,因此test.method()运行时成功解析。

基于Steven的回答,我理解了shims-vue.d.ts是使用组件作为打字稿类所必需的。但问题是它们都被认为是 Vue 实例。 在查看此文件内容时,这一点很明显:

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

目前,我发现的唯一干净方法是声明由我的组件实现的接口:

模型.ts:

export interface ITest {
method(): void;
}

Test.vue:

<template>
<div>{{method()}}</div>
</template>
<script lang="ts">
import { Component } from 'vue-property-decorator';
import Vue from 'vue';
import {ITest} from '@/views/test/model';
@Component
export default class Test extends Vue implements ITest {
public method(): string {
return 'hello';
}
}
</script>

测试规范:

import 'jest';
import {mount} from '@vue/test-utils';
import {ITest} from '@/views/test/model';
import Test from '@/views/test/Test.vue';
describe('Test.vue', () => {
let wrapper: any;
beforeEach(() => {
wrapper = mount(Test);
});
test('test method call', () => {
const test = wrapper.find(Test).vm as ITest;
expect(test.method()).toEqual('hello');
});
});

我注意到 Vue 文件能够使用其他 Vue 文件作为它们声明的类,这导致我尝试将 Jest 文件声明为 Vue 组件。令人惊讶的是,它有效 - 不需要额外的仅测试接口。

有两个步骤。首先,将.vue后缀添加到package.json中 Jest 的测试配置中:

{
"jest": {
"testMatch": [
"**/__tests__/**/*.test.ts",
"**/__tests__/**/*.test.vue"
],
}
}

其次,将测试文件重命名为.test.vue并将它们包装在<script>块中:

<script lang="ts">
import 'jest';
import { shallowMount } from '@vue/test-utils';
// Tests here...
</script>

现在您可以使用wrapper.vm作为实际声明的组件类类型,Vetur/Typescript将在IDE和编译器输出中完全满意。

在通话前添加这些内容。

// tslint:disable-next-line 
// @ts-ignore 

您还可以像这样合并现有的测试接口:

const test = wrapper.find(Test).vm as Test & {method()};

并不是说你应该在实践中这样做,但你的代码会运行......

解决此问题的正确方法是augmentVue's定义,以便typescript接受您的方法。 但这应该由 Vue 自动发生。您是否包括shims-vue.d.ts文件。 这就是打字稿魔术发生的地方?

https://v2.vuejs.org/v2/guide/typescript.html

话虽如此,我在使用 Vue 类语法时遇到了问题,不得不恢复到老式语法以避免打字稿抱怨:

<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
methods: {
method(): string {
return 'hello';
}
})
</script>

填充程序文件是 Vue 用你的组件来增强自己的方式。

Shims-vue.d.ts

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

多个 Vue 实例

有时Vue包含来自多个来源,这会弄乱打字稿。

尝试将其添加到您的tsconfig文件中。

{
"paths": {
"@/*": [
"src/*"
],
"vue/*": [
"node_modules/vue/*"
]
}

我有时甚至不得不为此添加 webpack 别名(不过这将是一个已发布的建筑物,因此不能解决您的问题):

'vue$': path.resolve(__dirname, 'node_modules', 'vue/dist/vue.esm.js'),

最新更新