-2

I’m trying to separate my TypeScript test configs for a Vite + React + Vitest project. The tsconfig.app.json and tsconfig.node.json files were created automatically by Vite; I only added my own tsconfig.test.json.

I now have:

  • tsconfig.json (references the others)

  • tsconfig.app.json

  • tsconfig.node.json

  • tsconfig.test.json

The problem is: ESLint does not recognize Vitest globals (describe, it, expect, etc.) in my test files. TypeScript compiles fine when running Vitest, but ESLint shows the error:

Cannot find name 'describe'. Do you need to install type definitions for a test runner?  Try npm i --save-dev @types/jest or npm i --save-dev @types/mocha.ts(2582)

Even though I already added "types": ["vitest/globals"] in my tsconfig.test.json.

My setup

tsconfig.test.json

{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "types": ["vitest/globals"]
  },
  "include": ["src/**/*.test.ts", "src/**/*.test.tsx", "src/tests/setup.ts"]
}

tsconfig.json

{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" },
    { "path": "./tsconfig.test.json" }
  ],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

vitest.config.ts

import { resolve } from 'path';
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './src/tests/setup.ts',
    css: true,
    typecheck: {
      tsconfig: './tsconfig.test.json',
    },
  },
  resolve: {
    alias: {
      '@': resolve(__dirname, './src'),
    },
  },
});

eslint.config.ts

import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';
import reactX from 'eslint-plugin-react-x';
import reactDom from 'eslint-plugin-react-dom';

export default tseslint.config(
  { ignores: ['dist'] },
  {
    extends: [
      js.configs.recommended,
      ...tseslint.configs.recommendedTypeChecked,
      ...tseslint.configs.stylisticTypeChecked,
    ],
    files: ['**/*.{ts,tsx}'],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
    },
    plugins: {
      'react-hooks': reactHooks,
      'react-refresh': reactRefresh,
      'react-x': reactX,
      'react-dom': reactDom,
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      'react-refresh/only-export-components': [
        'warn',
        { allowConstantExport: true },
      ],
      ...reactX.configs['recommended-typescript'].rules,
      ...reactDom.configs.recommended.rules,
    },
  },

  // Test files configuration
  {
    files: ['src/**/*.test.{ts,tsx}', 'src/tests/setup.ts'],
    languageOptions: {
      parserOptions: {
        project: './tsconfig.test.json',
      },
    },
  },
  {
    files: ['cypress/**/*.{ts,tsx}'],
    extends: ['plugin:cypress/recommended'],
  }
);

What I tried:

  • Running vitest → works fine, globals are recognized.
  • Adding "types": ["vitest/globals"] in tsconfig.app.json → ESLint stops complaining. But I don’t want my main app config polluted with test-only types.

How do I correctly configure ESLint + TypeScript so it recognizes Vitest globals (describe, it, etc.) from my tsconfig.test.json only without needing to add them into tsconfig.app.json?

5
  • Have you tried installing eslint-config-vitest-globals and use it in ESLint overrides for your test files? Commented Aug 18 at 5:27
  • You need to provide the globals in ESLint config, in the test files section, with e.g. npmjs.com/package/@vitest/eslint-plugin Commented Aug 18 at 9:11
  • @UncleBigBay Thanks 🙏. I tried eslint-config-vitest-globals but it didn’t solve it. The real fix was excluding test files from tsconfig.app.json so they’re only handled in tsconfig.test.json. Commented Aug 21 at 7:10
  • @jonrsharpe Thanks! I added @vitest/eslint-plugin for the rules (really helpful 👍), but the globals error was only fixed after excluding tests from tsconfig.app.json. Commented Aug 21 at 7:11
  • That sounds good! Commented Aug 21 at 7:55

1 Answer 1

0

Issue
tsconfig.app.json included the whole src folder, which also contained test files. This meant the tests were type-checked by both tsconfig.app.json and tsconfig.test.json, which caused conflicts and ESLint didn’t recognize Vitest globals.

Fix
Exclude test files from tsconfig.app.json so only tsconfig.test.json handles them.

tsconfig.app.json

{
  // Vite defaults...

  "exclude": ["src/**/*.test.ts", "src/**/*.test.tsx", "src/tests/setup.ts"]
}

tsconfig.test.json

{
  "compilerOptions": {
    "types": ["vitest/globals"],
    "lib": ["ES2020", "DOM"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx"
  },
  "include": ["src/**/*.test.ts", "src/**/*.test.tsx", "src/tests/setup.ts"]
}

After this change, ESLint recognized describe, it, expect, etc.

(Optional): I also added @vitest/eslint-plugin to my ESLint config. Not required for fixing the globals error, but helpful for extra rules and best practices in tests.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.