Vitest defineConfig, 'test' does not exist in type 'UserConfigExport'
Asked Answered
A

13

100

Trying to setup vitest on an already existing vite (vue 3, typescript) project.

My vite.config.ts looks like this:

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

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

But in VS code it complains:

vscode red lines under test prop

On hover I see:

Argument of type '{ test: { globals: boolean; environment: string; }; plugins: Plugin[]; }' is not assignable to parameter of type 'UserConfigExport'. Object literal may only specify known properties, and 'test' does not exist in type 'UserConfigExport'.ts(2345)

I can make it go away if I change this line:

import { defineConfig } from 'vite';

To:

import { defineConfig } from 'vitest/config';

But why? What's up with this? Why should I have to import defineConfig from vitest in order to get it to support the test property?

Apteral answered 6/5, 2022 at 19:12 Comment(0)
O
133

Short answer:

Because this is how TypeScript works. Vite config interface does not know anything about Vitest and TS does not allow excessive properties (properties not defined by the type/interface)


Because Vite itself does not know anything about Vitest and it's configuration. So Vitest must extend Vite config (defined as TS interface)

In order to use this extended interface (instead of the original one), you must first import it.

So instead of doing this (importing pure Vite config):

import { defineConfig } from 'vite';

do this (importing Vite config extended by Vitest):

import { defineConfig } from 'vitest/config';

Alternatively you can also use a "tripple slash command" as documented in Configuring Vitest

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

export default defineConfig({
  test: {
    // ...
  },
})
Olli answered 7/5, 2022 at 4:1 Comment(10)
not working for meAcronym
Neither for me, but this answer did: https://mcmap.net/q/211345/-vitest-defineconfig-39-test-39-does-not-exist-in-type-39-userconfigexport-39Signpost
This worked for me after I upgraded vite to 4.0.4, and vitest to 0.26.3Quean
I was already using the triple slash but didn't work. as @DavidHorm mentioned upgrading vite to 4.0.4 solved the issue for me :DTauromachy
Added the /// reference and the error went away for me. ThanksIsopleth
If it doesn't work, It's probably because vite and vitest are incompatible with each other. To verify this you can upgrade both libs to the latest version and see if the tsc error disappears. If that's the case you need to either upgrade vite or downgrade vitestMarquez
Didn't work for me but separating config by having vite.config.ts and vitest.config.ts helped me: https://mcmap.net/q/211345/-vitest-defineconfig-39-test-39-does-not-exist-in-type-39-userconfigexport-39.Reindeer
thanks @LorenzoRivosecchi i updated vite and it works with directiveGrout
Thanks a lot, also can be use in tsconfig.node.json, by add "types": ["vitest"] to it. :+1:Bandurria
@Bandurria Well yes, this works for this use case but has probably unwanted (IMHO) effect that only Vitest types are visible. If you are using more plugins (with type definitions), all of them needs to be specified there. (See the docs).Ley
W
20

I separated the files because i got the from this question and if i changed the import to vitest i got another error in the plugin react line.

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

vitest:

import { defineConfig } from 'vitest/config';

    export default defineConfig({
        test: {
          globals: true,
          environment: 'jsdom'
        },
      })

vite:

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

export default defineConfig({
  plugins: [react()],
  server: {
    port: 3000,
  },
})
Waxler answered 5/1, 2023 at 15:13 Comment(2)
This feels like the most elegant solution of the ones posted here.Stuck
Be aware that this means all options in your vite.config will be ignored by vitest.Christiniachristis
P
19

Here is what I did in case someone is still looking for a solution. I created my own type and extended to UserConfig.

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

interface VitestConfigExport extends UserConfig {
  test: InlineConfig;
}
...

Then I casted the type of config object to my custom interface -

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);

This also enabled intellisense for new test property. Also, you don't need to declare /// <reference types="vitest" />. It might help.

Phippen answered 15/11, 2022 at 23:30 Comment(2)
works with nuxt3, thanksLilybel
Note that using as means that type-checking is entirely circumvented and you won't get type errors if anything in your object structure is incorrect. Ideally, use satisfies.Aberration
D
17

I was in a similar situation, asking me the same thing and end up doing this:

/// <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
});

It may be helpful.

Decencies answered 25/7, 2022 at 8:19 Comment(0)
S
5

sunny prakash solution is quite good, but it allow wrong type in config due to as VitestConfigExport construction.

Better way is to move config to separate constant and use it

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);
Something answered 29/4, 2023 at 14:2 Comment(0)
R
5

I had a similar issue that was resolved by using a version of vitest and vite that were compatible. In my case the latest version of each. I assume using versions that were released around the same time frame would work as well.

yarn install -D vitest vite
Reticulum answered 4/1 at 20:19 Comment(0)
W
4

We can use mergeConfig method from vite or vitest/config entries to merge Vite config with Vitest config:

import { defineConfig as defineViteConfig, mergeConfig } from 'vite';
import { defineConfig as defineVitestConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';

const viteConfig = defineViteConfig({
  plugins: [react()],
});

const vitestConfig = defineVitestConfig({
  test: {
    // ...
  },
});

export default mergeConfig(viteConfig, vitestConfig);
Wean answered 4/10, 2023 at 12:18 Comment(1)
This works, makes sense, really wish we didn't have to do it, thanks for sharing!Whisler
P
2

None of the options listed above helped me. Eventually, I've managed to solve this issue using the type augmentation feature:

import type { UserConfig as VitestUserConfig } from 'vitest/config';
import { defineConfig } from 'vite';

declare module 'vite' {
  export interface UserConfig {
    test: VitestUserConfig['test'];
  }
}

export default defineConfig({
  // add your vite configuration here

  test: {
    // add your vitest configuration here
  },
});
Pentup answered 14/10, 2023 at 15:12 Comment(0)
P
1

The above method doesn't work for me, then I try this, It work.

/// <reference types="vitest" />
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx'; // 支持jsx语法

// https://vitejs.dev/config/
export default defineConfig(() => {
  return {
    plugins: [vue(), vueJsx()],
    test: {
      globals: true,
      environment: 'jsdom',
      transformMode: { web: [/.[tj]sx$/] },
    },
  };
});
Pentlandite answered 31/8, 2023 at 4:59 Comment(0)
T
1

Replacing the function with an arrow function worked for me. Mentioned at https://github.com/vitest-dev/vitest/discussions/1106#discussioncomment-2531279

export default defineConfig(() => ({
  build: {
    // ...
  },
  test: {
    // ...
  },
}));
Tylertylosis answered 2/1 at 2:24 Comment(0)
M
1

as 2024 you can just import vitest/config which pulls the extended types automatically

import {defineConfig} from "vite";
import "vitest/config" // <-- just dummy import

export default defineConfig({
  test: {
    // your stuff here
  }
})
Marisamariscal answered 21/3 at 20:9 Comment(0)
M
0

It might be because you have multiple versions of vite installed. Search in your package-lock or yarn-lock file to find the entries for vite, and make sure there's only one of them. After that, I got it to work using the triple-slash.

Mylander answered 14/8, 2023 at 19:56 Comment(0)
O
-2

I had a similar issue with my project, but after adding /// <reference types="vitest" /> this line at the top of the file, the error is gone.

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

export default defineConfig({
  ...
  test: {
   ...
  },
});
Oft answered 8/5, 2023 at 9:5 Comment(1)
This comment brings no value. It's the same as what the previous post states as an alternative option, and it is apparent from the comments bellow it that for some it works and for some, it doesn't.Esurient

© 2022 - 2024 — McMap. All rights reserved.