Headshot of Marius Schulz
Marius Schulz Front End Engineer

TypeScript 2.3: Type-Checking JavaScript Files with --checkJs

Up until TypeScript 2.2, type checking and error reporting were only available within .ts files. Starting with TypeScript 2.3, the compiler can now type-check and report errors for plain .js files as well:

let foo = 42;

// [js] Property 'toUpperCase' does not exist on type 'number'.
let upperFoo = foo.toUpperCase();

There's a new --checkJs flag which enables type checking for all .js files by default. Additionally, three new directives in the form of comments allow for more granular control over which pieces of JavaScript code should be checked:

  • Use // @ts-check to opt in to type checking for a single file.
  • Use // @ts-nocheck to opt out of type checking for a single file.
  • Use // @ts-ignore to opt out of type checking for a single line.

These options leave you with a blacklist approach and a whitelist approach. Note that either way, the --allowJs option should be set to true so that JavaScript files are allowed to be included in the compilation in the first place.

The Blacklist Approach

The idea behind the blacklist approach is to type-check every JavaScript file by default. This can be achieved by setting the --checkJs compiler option to true. You can blacklist specific files by adding the // @ts-nocheck comment at the top of each of these files.

I would recommend this approach if you have a smallish JavaScript code base that you want to type-check in one go. If an error is reported, you can either fix it right away, ignore the line that caused the error using // @ts-ignore, or ignore the entire file using // @ts-nocheck.

The Whitelist Approach

The idea behind the whitelist approach is to only type-check selected JavaScript files by default. This can be achieved by setting the --checkJs compiler option to false and adding the // @ts-check comment at the top of each of the selected files.

I would recommend this approach if you want to gradually introduce type checking in a large JavaScript code base. This way, you won't be overwhelmed with too many errors all at once. Whenever you're working on a file, consider adding // @ts-check and fixing potential type errors first, effectively implementing a creeping migration.

Migrating from JavaScript to TypeScript

Once your entire code base is type-checked, it's a lot easier to migrate from JavaScript (and .js files) to TypeScript (and .ts files) entirely. Using either the whitelist or the blacklist approach, you can get quick wins and, at the same time, prepare a migration to a fully statically typed code base, powered by TypeScript.

This post is part of the TypeScript Evolution series:

  1. TypeScript 2.0: Non-Nullable Types
  2. TypeScript 2.0: Control Flow Based Type Analysis
  3. TypeScript 2.0: Acquiring Type Declaration Files
  4. TypeScript 2.0: Read-Only Properties
  5. TypeScript 2.0: Tagged Union Types
  6. TypeScript 2.0: More Literal Types
  7. TypeScript 2.0: The never Type
  8. TypeScript 2.0: Built-In Type Declarations
  9. TypeScript 2.1: async/await for ES3/ES5
  10. TypeScript 2.1: External Helpers Library
  11. TypeScript 2.1: Object Rest and Spread
  12. TypeScript 2.1: keyof and Lookup Types
  13. TypeScript 2.1: Mapped Types
  14. TypeScript 2.1: Improved Inference for Literal Types
  15. TypeScript 2.1: Literal Type Widening
  16. TypeScript 2.1: Untyped Imports
  17. TypeScript 2.2: The object Type
  18. TypeScript 2.2: Dotted Properties and String Index Signatures
  19. TypeScript 2.2: Null-Checking for Expression Operands
  20. TypeScript 2.2: Mixin Classes
  21. TypeScript 2.3: Generic Parameter Defaults
  22. TypeScript 2.3: The --strict Compiler Option
  23. TypeScript 2.3: Type-Checking JavaScript Files with --checkJs
  24. TypeScript 2.3: Downlevel Iteration for ES3/ES5
  25. TypeScript 2.4: String Enums
  26. TypeScript 2.4: Weak Type Detection
  27. TypeScript 2.4: Spelling Correction
  28. TypeScript 2.4: Dynamic import() Expressions
  29. TypeScript 2.5: Optional catch Binding
  30. TypeScript 2.6: JSX Fragment Syntax
  31. TypeScript 2.7: Numeric Separators
  32. TypeScript 2.7: Strict Property Initialization
  33. TypeScript 2.8: Per-File JSX Factories
  34. TypeScript 2.8: Conditional Types
  35. TypeScript 2.8: Mapped Type Modifiers