Vitest DefineConfig,“UserConfigExport”类型中不存在“test”

Wil*_*llD 91 typescript vite vitest

尝试在现有的 vite(vue 3,typescript)项目上设置 vitest。

我的 vite.config.ts 看起来像这样:

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  test: {
    globals: true,
    environment: 'jsdom',
  },
  plugins: [vue()],
});
Run Code Online (Sandbox Code Playgroud)

但在 VS 代码中它会抱怨:

vscode 测试 prop 下的红线

悬停时我看到:

类型参数 '{ test: { globals: boolean; 环境:字符串;}; 插件:插件[];}' 不可分配给“UserConfigExport”类型的参数。对象文字只能指定已知属性,并且“UserConfigExport”类型中不存在“test”。ts(2345)

如果我改变这一行,我可以让它消失:

import { defineConfig } from 'vite';
Run Code Online (Sandbox Code Playgroud)

到:

import { defineConfig } from 'vitest/config';
Run Code Online (Sandbox Code Playgroud)

但为什么?这是怎么回事?为什么我必须从 vitest 导入 DefineConfig 才能使其支持测试属性?

Mic*_*evý 119

简短回答:

因为这就是 TypeScript 的工作原理。Vite config 接口不了解 Vitest 的任何信息,并且 TS 不允许过多的属性(未由类型/接口定义的属性)


因为Vite本身并不了解Vitest及其配置。所以Vitest必须扩展Vite config(定义为TS接口)

为了使用这个扩展接口(而不是原始接口),您必须首先导入它。

因此,不要这样做(导入纯 Vite 配置):

import { defineConfig } from 'vite';
Run Code Online (Sandbox Code Playgroud)

这样做(导入由 Vitest 扩展的 Vite 配置):

import { defineConfig } from 'vitest/config';
Run Code Online (Sandbox Code Playgroud)

或者,您也可以使用“三重斜杠命令”,如配置 Vitest中所述

/// <reference types="vitest" />
import { defineConfig } from 'vite'

export default defineConfig({
  test: {
    // ...
  },
})
Run Code Online (Sandbox Code Playgroud)

  • 不为我工作 (37认同)
  • 在我将 vite 升级到 4.0.4,并将 vitest 升级到 0.26.3 后,这对我有用 (5认同)
  • 对我来说都不是,但这个答案确实如此:/sf/answers/5117421361/ (2认同)

小智 19

这是我所做的,以防有人仍在寻找解决方案。我创建了自己的类型并扩展到UserConfig.

...
import type { InlineConfig } from 'vitest';
import type { UserConfig } from 'vite';

interface VitestConfigExport extends UserConfig {
  test: InlineConfig;
}
...
Run Code Online (Sandbox Code Playgroud)

然后我将对象的类型投射config到我的自定义界面 -

export default defineConfig({
  plugins: [solidPlugin()],
  server: {
    port: 3000,
  },
  test: {
    environment: 'jsdom',
    globals: true,
    transformMode: {
      web: [/\.[jt]sx?$/],
    },
    setupFiles: './setupVitest.ts',
  },
  build: {
    target: 'esnext',
  },
} as VitestConfigExport);
Run Code Online (Sandbox Code Playgroud)

这也为新test属性启用了智能感知。另外,您不需要声明/// <reference types="vitest" />. 这可能有帮助。


Jon*_*ego 17

我分离了这些文件,因为我从这个问题中得到了,如果我将导入更改为 vitest,我会在插件反应行中遇到另一个错误。

  • vite.config.ts
  • vitest.config.ts

维斯特:

import { defineConfig } from 'vitest/config';

    export default defineConfig({
        test: {
          globals: true,
          environment: 'jsdom'
        },
      })
Run Code Online (Sandbox Code Playgroud)

维特:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    port: 3000,
  },
})
Run Code Online (Sandbox Code Playgroud)

  • 这感觉像是这里发布的最优雅的解决方案。 (6认同)

小智 16

我也遇到过类似的情况,问了我同样的事情,最后我这样做了:

/// <reference types="vitest" />
import { defineConfig } from 'vite';
import type { UserConfig as VitestUserConfigInterface } from 'vitest/config';

const vitestConfig: VitestUserConfigInterface = {
  test: {
    // vitest config, with helpful vitest typing :)
  }
};

export default defineConfig({
  test: vitestConfig.test,
  // and now: just vite config
});

Run Code Online (Sandbox Code Playgroud)

这可能会有所帮助。


Eug*_*sky 5

sunny prakash 解决方案非常好,但由于as VitestConfigExport构造原因,它允许配置中的错误类型。

更好的方法是将配置移动到单独的常量并使用它

import type { InlineConfig } from 'vitest';
import type { UserConfig } from 'vite';

type ViteConfig = UserConfig & { test: InlineConfig };
const config: ViteConfig = {
  // other config
  test: {
    environment: 'jsdom',
  },
};
export default defineConfig(config);
Run Code Online (Sandbox Code Playgroud)