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.
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:
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:
{
"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:
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:
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:
| Action | Controlled by | Default |
|---|---|---|
| Include JavaScript files in compilation | allowJs | Off |
| Type-check JavaScript files and report errors | checkJs | Off |
| Emit JavaScript files to the output folder | allowJs and outDir | Copies or transpiles |
| Generate type declaration files from JavaScript | declaration and emitDeclarationOnly | Off |
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:
// 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:
{
"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:
// 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:
// 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:
| Setting | Effect |
|---|---|
| allowJs off | JavaScript files are ignored entirely. |
| allowJs on, checkJs off | JavaScript files are compiled but not type-checked. |
| allowJs on, checkJs on | JavaScript 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
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.
Frequently Asked Questions
Does allowJs type-check my JavaScript files?
Can I use allowJs without checkJs?
What happens to JavaScript files during compilation with allowJs?
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.
More in this topic
TypeScript Compiler Explained
The TypeScript compiler (tsc) turns .ts files into .js files while checking types. Learn what it does, how to use it, and how it fits your workflow.
Set Up ESLint for TypeScript
Install and configure ESLint with typescript-eslint to catch bugs and enforce consistent code style in your TypeScript project.
Pick Utility Type in TypeScript
Pick creates a new type by selecting only the properties you name from an existing type. Use it to build focused types for specific views, API responses, or function parameters.