Use allowJs in TypeScript

allowJs lets TypeScript accept .js files as inputs alongside .ts files. Learn how to enable it, when to use it, and how it helps incremental migration.

5 min read

allowJs is a TypeScript compiler option that tells the compiler to accept JavaScript files as inputs. Without it, TypeScript only processes TypeScript files. With it, your existing JavaScript can live alongside new TypeScript code in the same project.

This option is the foundation of gradual adoption. You do not need to rename every file before TypeScript can compile your project.

How allowJs Works

When this option is turned on, TypeScript treats JavaScript files as part of your project. It reads them, optionally checks them if checkJs is also enabled, and emits them to the output directory just like it emits compiled TypeScript.

Here is the flow with the option enabled:

TypeScript compilation with allowJs enabled

Both files feed into the same compiler and land in the output folder. The JavaScript file passes through largely unchanged in shape, while the TypeScript file is type-checked and transpiled to plain JavaScript. If the TypeScript file has a type error, the compiler reports it as a diagnostic message during the build; it is not a file written to disk the way the two output files are.

Enable allowJs

Add it to your tsconfig.json file under the compiler options:

jsonjson
{
  "compilerOptions": {
    "allowJs": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}

This configuration turns the option on, sends compiled output to a separate directory, and points the compiler at the source folder. TypeScript now includes any JavaScript files it finds under that folder alongside the TypeScript files, compiling both together.

To see why this matters, compare what happens with the option off. This import statement looks completely normal, but the compiler refuses to resolve it while the setting stays off:

typescripttypescript
import { helper } from "./utils";

If a file named utils.js sits right next to this module, TypeScript still will not look inside it, and the build fails with a resolution error:

texttext
Cannot find module './utils' or its corresponding type declarations.

Turning the option on resolves the import immediately, and the JavaScript file becomes part of the compiled output.

What allowJs Does With JavaScript Files

TypeScript can do several things with JavaScript files once this option is on:

ActionControlled byDefault
Include JavaScript files in compilationallowJsOff
Type-check JavaScript files and report errorscheckJsOff
Emit JavaScript files to the output folderallowJs and outDirCopies or transpiles
Generate type declaration files from JavaScriptdeclaration and emitDeclarationOnlyOff

When only the include option is on and checking stays off, TypeScript does not report type errors from JavaScript files. It simply includes them in the compilation and emits them, the same way it would emit a TypeScript file with no errors.

If a JavaScript file uses newer syntax than the configured target, TypeScript transpiles it down to match:

javascriptjavascript
// src/legacy.js
export const greet = (name) => `Hello, ${name}`;

With an older target such as ES5, TypeScript converts the arrow function and template literal in this file down to ES5 syntax in the output. With a newer target such as ES2022, and source code that already uses only ES2022 features, the file passes through unchanged.

Using allowJs for Migration

The most common use of this option is during a JavaScript-to-TypeScript migration. Here is a typical setup:

jsonjson
{
  "compilerOptions": {
    "target": "es2022",
    "outDir": "./dist",
    "rootDir": "./src",
    "allowJs": true,
    "checkJs": false,
    "strict": false
  },
  "include": ["src/**/*"]
}

This configuration accepts both JavaScript and TypeScript files, but keeps checking lenient while the migration is in progress. It does not report errors in JavaScript files, since checking stays off, and it uses relaxed type rules instead of strict mode so existing TypeScript files do not suddenly fail to compile.

You can rename files from JavaScript to TypeScript one at a time. The rest of the project keeps compiling because the option handles the remaining JavaScript files automatically. As each renamed file starts passing type checking, you can turn on individual strict-mode flags for it, or tighten the whole project once every file has been converted.

There is no required order for renaming files. Many teams start with the files that change most often, since those get the most benefit from type checking, and leave stable utility files in JavaScript until later.

allowJs and Module Imports

When importing between a JavaScript file and a TypeScript file, write the import path without a file extension, the same way you would between two TypeScript files:

typescripttypescript
// In a .ts file, importing from a .js file
import { oldHelper } from "./legacy-utils";
 
// In a .js file, importing from a .ts file
import { newHelper } from "./new-utils";

Both imports resolve correctly once the option is enabled, regardless of which file is JavaScript and which is TypeScript. This example assumes a commonjs module setting, which is common in a Node.js project midway through migration; TypeScript compiles both import statements down to require calls in the output.

JavaScript files that already use require() instead of an import statement do not need to change at all:

javascriptjavascript
// legacy-utils.js
const { newHelper } = require("./new-utils");

TypeScript reads this call the same way it reads an import statement and resolves the path to the TypeScript module, so the imported helper is available with its inferred type.

When to Keep allowJs On

Some projects keep this option turned on permanently. That makes sense when:

  • You have third-party JavaScript files you cannot convert.
  • Part of your team writes JavaScript while another part writes TypeScript.
  • You have generated JavaScript that should be included but not type-checked.
  • You want to add TypeScript to a large project without a hard cutoff date.

Turning the option on adds little overhead in most projects, since TypeScript already scans every file matched by your include pattern. The option mainly changes which file types are treated as valid input, rather than adding a separate scanning pass.

allowJs vs checkJs

These two options are related but independent:

SettingEffect
allowJs offJavaScript files are ignored entirely.
allowJs on, checkJs offJavaScript files are compiled but not type-checked.
allowJs on, checkJs onJavaScript files are compiled and type-checked.

You cannot turn on checking without also turning on this option. The compiler requires it to be enabled before it can check JavaScript files at all, since checking depends on JavaScript files being part of the compilation in the first place.

A common pattern during migration is to enable the include option project-wide while leaving checking off, then turn checking on for individual files with a pragma comment as you clean them up. This gives you type errors exactly where you are ready to fix them, instead of a flood of errors across every JavaScript file at once.

For more on type-checking JavaScript, see Use checkJs in TypeScript.

When allowJs Is Not Enough

This option lets JavaScript files compile, but it does not type-check them, and it does not add any types on its own. A file can still have a typo in a property name or a wrong argument count and compile without a single warning.

To get error reports inside JavaScript files, enable checking as well, either for the whole project or per file with an inline pragma comment. To add real types without renaming files, write JSDoc annotations above your functions and variables; TypeScript reads those comments the same way it reads a type annotation in a TypeScript file.

For the full migration story, see Migrate JavaScript to TypeScript Step by Step.

Common Mistakes

Forgetting to set an output folder. If you compile with the option on and no outDir, TypeScript may overwrite your source JavaScript files with compiled output. Always set that output folder to a separate directory from your source files.

Including node_modules by accident. An include pattern like src/**/* keeps the dependency folder out. If you widen the pattern and accidentally include it, TypeScript tries to compile every JavaScript file in your dependencies too, which is slow and unnecessary.

Expecting type checking without turning it on. Enabling this option alone gives no type errors inside JavaScript files. You need checking turned on project-wide, or a @ts-check comment at the top of an individual file, to see errors there.

Importing with the file extension included. If you write an import path that ends in the JavaScript extension from a TypeScript file, TypeScript looks for a file with that literal name plus a TypeScript extension, which usually does not exist. Omit the extension when importing between TypeScript and JavaScript files.

Rune AI

Rune AI

Key Insights

  • allowJs lets TypeScript include .js files during compilation.
  • Without allowJs, TypeScript ignores .js files and only compiles .ts files.
  • allowJs does not type-check JavaScript; use checkJs for that.
  • It is essential for projects that want to migrate gradually.
  • Combine with outDir to keep compiled .js output separate from source files.
RunePowered by Rune AI

Frequently Asked Questions

Does allowJs type-check my JavaScript files?

No. allowJs only tells TypeScript to include .js files during compilation and emit them as output. To type-check JavaScript files, you also need checkJs: true.

Can I use allowJs without checkJs?

Yes. allowJs and checkJs are independent. allowJs includes JS files in compilation; checkJs reports type errors in them. You can use allowJs without checkJs for a lenient migration setup.

What happens to JavaScript files during compilation with allowJs?

TypeScript copies or transpiles them to the output directory based on your target setting. If target is ES2022 and the JS file already uses ES2022 syntax, TypeScript emits it as-is.

Conclusion

allowJs is the compiler option that lets .js and .ts files coexist in the same TypeScript project. Enable it during migration, and keep it on as long as your project has both file types. It is the foundation for gradual adoption of TypeScript.