Mixed JS Projects

Learn how to run JavaScript and TypeScript together safely in the same project. This guide covers allowJs, checkJs, JSDoc typing, gradual strictness, and safe incremental adoption strategies.

On this page

Why mixed JS and TS projects are common

Most real-world migrations to TypeScript do not start from scratch. Teams often need to maintain existing JavaScript files while gradually introducing TypeScript. A mixed JS/TS setup allows incremental adoption without freezing feature development.

Enabling allowJs

The allowJs option lets TypeScript include JavaScript files in the compilation process.

{
  "compilerOptions": {
    "allowJs": true,
    "strict": true
  }
}

This allows .js and .ts files to coexist in the same src directory.

Using checkJs for gradual type checking

The checkJs option enables type checking inside JavaScript files without converting them to TypeScript yet.

{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true
  }
}

This is useful when you want type safety but cannot fully migrate to .ts files yet.

Adding types with JSDoc

You can add type information to JavaScript files using JSDoc comments. TypeScript understands these annotations.

/**
 * @param {number} a
 * @param {number} b
 * @returns {number}
 */
function add(a, b) {
  return a + b;
}

This improves safety even before converting the file to TypeScript.

Gradual strictness

In mixed projects, strict mode should remain enabled for TypeScript files. JavaScript files may temporarily rely on looser checks, but the goal should be to move toward stricter enforcement over time.

Folder-based migration strategy

One effective approach is to migrate folder by folder. For example:

  • Convert shared utilities first.
  • Convert API and data models next.
  • Convert feature modules gradually.

Avoid spreading any across the project

In mixed environments, any can spread quickly from JavaScript modules into TypeScript files. Keep boundaries clear and use unknown plus narrowing when importing loosely typed modules.

Build and runtime considerations

When compiling, ensure your build process handles both .js and .ts files correctly. Avoid mixing compiled output inside the source directory. Keep dist or build directories separate from src.

When to remove allowJs

Once most files are migrated and confidence is high, you can disable allowJs and require new code to be written in TypeScript. This marks the final stage of migration.

Common mistakes

  • Leaving allowJs enabled permanently without a migration plan.
  • Mixing compiled JavaScript and source files in the same folder.
  • Ignoring type errors in JavaScript when checkJs is enabled.
  • Using any as a permanent solution instead of a temporary bridge.

Production guidance

  • Use allowJs only as a transition tool.
  • Enable checkJs to improve safety during migration.
  • Add JSDoc types to critical JavaScript modules.
  • Define clear milestones to remove legacy JS over time.
  • Keep strict mode enabled for all TypeScript code.

Section complete

You have now covered real-world TypeScript usage: async flows, error handling, third-party libraries, community type definitions, migration strategies, and mixed JS environments. The next logical step is expanding into advanced architecture patterns or moving toward Node.js APIs and full-stack integration.