Q24 of 38 · TypeScript

What are the most important `tsconfig.json` settings for a Playwright test project?

TypeScriptMidtypescripttsconfigplaywrightconfigurationbuild

Short answer

Short answer: `target` and `module` set output JS version and module format. `strict: true` enables null and implicit-any safety. `moduleResolution: 'bundler'` (or 'node16') governs import resolution. `paths` enables import aliases. `include` scopes what's compiled. `skipLibCheck` skips node_modules .d.ts for faster builds.

Detail

A Playwright TypeScript project needs a tsconfig tuned for test code — slightly different from a frontend or library tsconfig.

Key settings:

target: The JavaScript language level for emitted code. ES2022 is safe for Node 18+; it supports top-level await, class fields, and Array.at.

module: The module format. CommonJS for Node.js test environments; ESNext if you're using an ESM-native runner (Vitest, Playwright + Vite).

strict: Enable. Always. New projects have no excuse.

moduleResolution: "bundler" (TypeScript 5.0+) or "node16" for ESM-correct resolution. The older "node" resolves incorrectly for ESM-style imports.

baseUrl + paths: paths: { "@tests/*": ["./tests/*"] } enables import aliases, avoiding deep relative paths in test files.

include / exclude: Scope the compiler to your test directory — don't accidentally compile node_modules or output directories.

outDir / noEmit: Most test projects use noEmit: true (type-check only; the test runner handles transpilation). outDir is needed if you do emit.

esModuleInterop: Should be true to allow default imports from CommonJS modules (import path from 'path' instead of import * as path from 'path').

// EXAMPLE

// tsconfig.json for a Playwright TypeScript project
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "CommonJS",
    "lib": ["ES2022"],
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "baseUrl": ".",
    "paths": {
      "@fixtures/*": ["./fixtures/*"],
      "@pages/*":    ["./pages/*"],
      "@utils/*":    ["./utils/*"]
    },
    "noEmit": true,               // tsc is type-checker only
    "skipLibCheck": true,         // skip node_modules .d.ts
    "noUnusedLocals": true,
    "noUnusedParameters": true
  },
  "include": ["tests/**/*", "fixtures/**/*", "pages/**/*", "utils/**/*"],
  "exclude": ["node_modules", "test-results", "playwright-report"]
}

// WHAT INTERVIEWERS LOOK FOR

Understanding of the key options and why each matters for test code. `strict: true` as non-negotiable. `noEmit: true` for type-checking only. Path aliases for import clarity. Excluding output directories. This is a practical config question — knowing the defaults vs what needs overriding.

// COMMON PITFALL

Including `src/**/*` or the project root in `include` — this can pull in application source files into the test type scope, causing type conflicts and longer compile times.