Installing TypeScript and Initialising tsconfig.json

8 min read

If you worked through TypeScript for QA, you already installed TypeScript in a fresh folder. This lesson is different: you're installing TypeScript into an existing JavaScript project that is already running tests. The goal is to add TypeScript without breaking anything — the existing tests must keep running at every step.

Step 1: Install TypeScript

Open your existing project folder in a terminal. Install TypeScript as a development dependency:

npm install --save-dev typescript @types/node

@types/node gives you type definitions for Node.js built-ins — process.env, Buffer, path, fs. You almost certainly need it even if your tests run in a browser, because most Cypress and Playwright config files run in Node.

Check the install worked:

npx tsc --version
# Version 5.x.x

Do not install TypeScript globally (npm install -g typescript). Different projects pin different TypeScript versions, and a global install creates subtle mismatches. --save-dev keeps it scoped to this project.

Step 2: Create tsconfig.json

Run:

npx tsc --init

This generates a tsconfig.json at your project root with most options listed but commented out. You are going to replace it with a migration-friendly configuration.

Step 3: Migration-friendly tsconfig.json

The default tsconfig.json generated by --init is configured for a greenfield TypeScript project. For a migration, you need different defaults — permissive enough that existing JavaScript continues to compile, strict enough that TypeScript is actually useful on the files you convert.

Replace the generated file with this:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "commonjs",
    "allowJs": true,
    "checkJs": false,
    "strict": false,
    "noImplicitAny": false,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["**/*.ts", "**/*.js"],
  "exclude": ["node_modules", "dist", "cypress/screenshots", "cypress/videos"]
}

The two critical settings for migration:

  • allowJs: true — the TypeScript compiler processes .js files alongside .ts files. Without this, TypeScript only sees files you've already renamed.
  • checkJs: false.js files are included but not type-checked. They compile, but no errors are reported for them. This keeps the existing project green from day one.

The two settings you are deliberately leaving permissive:

  • strict: false — turns off the full strict suite. You'll enable these flags incrementally in Lesson 3 of this chapter.
  • noImplicitAny: false — parameters without explicit types are silently any. You'll turn this on after converting your first batch of files.

Step 4: Add type-check scripts

In package.json:

{
  "scripts": {
    "type-check": "tsc --noEmit",
    "type-check:watch": "tsc --noEmit --watch"
  }
}

--noEmit tells TypeScript to check types without writing any output files. This is what you want in a CI check — you're not compiling to a dist/ folder, you're just verifying the types are correct.

Step 5: Verify everything is green

Run:

npm run type-check

With allowJs: true, checkJs: false, and strict: false, this should produce zero errors even though the project is still entirely JavaScript. If you see errors, they are from the node_modules or generated files leaking into the compiler's scope — check your exclude list.

Step 1 of 5

Install TypeScript

npm install --save-dev typescript @types/node — scoped to the project, not global. Verify with npx tsc --version.

The outDir question

You may notice the migration config above has no outDir. That's intentional. During migration, most test runners (Cypress, Playwright, Jest with ts-jest) compile TypeScript themselves — they don't use your tsconfig.json's output directory. Setting outDir would cause confusion if someone runs npx tsc and ends up with a dist/ folder of compiled test files that nobody uses.

If you have utility scripts or a shared library that needs a real build step, add outDir to a separate tsconfig.build.json and keep the base config clean.

What about Cypress-specific config?

Cypress looks for a tsconfig.json in the cypress/ directory first. If it doesn't find one, it uses the project root. For a migration, the root config with allowJs: true is sufficient to start — Cypress will pick it up.

Once you've converted most Cypress files, you can add a cypress/tsconfig.json that extends the root config and adds Cypress-specific type declarations:

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "types": ["cypress", "node"]
  },
  "include": ["**/*.ts", "**/*.js"]
}

The "types": ["cypress", "node"] line restricts auto-loaded type packages to just Cypress and Node, preventing browser DOM types from conflicting with Cypress's own DOM definitions.

⚠️ Common mistakes

  • Running npx tsc without --noEmit and being surprised by a dist/ folder. During migration, always use npm run type-check (which passes --noEmit), not bare npx tsc. Add dist/ to .gitignore just in case.
  • Not excluding screenshot and video directories. Cypress writes screenshots and videos to cypress/screenshots and cypress/videos. If these directories contain JavaScript files, TypeScript will try to include them. Add both to exclude.
  • Forgetting resolveJsonModule: true. If your tests import fixture files with import data from "./fixtures/users.json", TypeScript needs this option to parse the import. Without it, you'll see Cannot find module './fixtures/users.json' errors as soon as you start converting test files.

🎯 Practice task

Add TypeScript to your JavaScript test project from the JavaScript for QA course, or clone a small Cypress or Playwright JavaScript starter.

  1. Run npm install --save-dev typescript @types/node.
  2. Run npx tsc --init and then replace the generated tsconfig.json with the migration-friendly config from this lesson.
  3. Add the type-check script to package.json.
  4. Run npm run type-check. Confirm it exits with zero errors.
  5. Stretch: deliberately introduce a mistake in the tsconfig — set include to ["src/**/*.ts"] without a matching src/ directory — and observe what happens. Then restore the correct include pattern. Understanding how the compiler resolves files saves hours of debugging in real migrations.

Once type-check passes with zero errors on an all-JavaScript codebase, you have a stable base to start converting files. The next lesson covers the allowJs and checkJs settings in depth.

// tip to track lessons you complete and pick up where you left off across devices.