How to compile plain *.js (JavaScript) files with the TypeScript Compiler

Challenge

Let’s say you’ve been tasked with researching what porting your existing JavaScript solution to TypeScript may look like or maybe you’re curious what this process would be like before you propose it to a lead or project manager.

The first hurdle you may stumble upon is – the tsc (TypeScript compiler) requires all of your files end with a .ts file extension. This can make quickly prototyping a port challenging. To get an idea of what a port to TypeScript will look like you don’t want to deal with first renaming all of your files to .ts. Especially since there are probably files you want to not rename to TypeScript (like jQuery or AngularJS etc.

And since:

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.

it seems reasonable that you could acquire the benefits of the TypeScript compiler for even your existing JavaScript codebase.

Challenge Accepted.

The TypeScript compiler is open source, so let’s take a dive into the compiler to see if this is something we can work around…

What are the steps we need to accomplish to make the compiler accept plain .js files?

  1. Get It
  2. Copy it
  3. Hack it
  4. Use it

Get it

Before we can get too far, let’s first install the compiler onto our system.

I’ll use npm to install typescript

npm install -g typescript

Note the -g here tells npm to install typescript globally. This adds the TypeScript compiler to your PATH so you can get right at tsc‘ing your TypeScript code.

Copy it

We probably don’t want to modify the globally installed version of tsc so we’ll create a copy on our system to play around with. But, before we can do that we need to find where it is.

If on Windows or Mac

where tsc

NOTE: if you’re using the PowerShell console on windows be sure to type out where.exe tsc because where is aliased to Where-Object in PowerShell which won’t help us out in this case.

Once you’ve found the path to your version of tsc

Mine was in

  • C:\Users\jason\AppData\Roaming\npm\tsc
  • C:\Users\jason\AppData\Roaming\npm\tsc.cmd

Look at the contents of the tsc.cmd for Windows and tsc for non Windows machines. You’ll notice that they are essentially executing node.exe passing in an argument to another tsc file in the node_modules path.

Take the two tsc and tsc.cmd files, copy them into a working folder MyJSCompiler and rename them. I named mine jsc and he shall be my squishy. Then take the contents of the node_modules/typescript/* folder (and path structure) and copy them to your working directory.

When you’re done you should have a directory that looks something like this


??--MyJSCompiler
  |   jsc                 <-- notice the re-named file from tsc -> jsc
  |   jsc.cmd             <-- notice the re-named file from tsc.cmd -> jsc.cmd
  |   
  ----node_modules
      ----.bin
      |       tsc
      |       tsc.cmd
      |       
      ----typescript
          |   .npmignore
          |   CopyrightNotice.txt
          |   LICENSE.txt
          |   package.json
          |   README.txt
          |   ThirdPartyNoticeText.txt
          |   
          ----bin
              |   lib.d.ts
              |   tsc
              |   tsc.js
              |   typescript.js
              |   
              ----resources
                  |   diagnosticMessages.generated.json
                  |   
                  ----(*.json files excluded for brevity)

Now you should be able to call your local version of jsc at the command line.

Hack it

Since we have a local version we can hack on now, let’s find out what needs to change. Thanks to Ryan for already giving us a clue here.

Open up the node_modules/typescript/bin/tsc.js file (in our working directory from the previous step) and apply the below diff/changes.

     function isTSFile(fname) {
-        return isFileOfExtension(fname, ".ts");
+        return isFileOfExtension(fname, ".ts") || isFileOfExtension(fname, ".js");
     }

We’ve now implemented a small tweak to the TypeScript compiler that allows us to compile plain JavaScript files.

Use it

I won’t be going into how to use the tsc compiler in this post, but you can now call the compiler passing along your *.js files and begin learning what changes you will need to make to your existing codebase to satisfy the compiler.

Be sure to use the --out FILE or --outDir DIRECTORY options because if you don’t the compiler will take the input javascript file and overwrite it with it’s compiled version.

!!WARNING!! I’ll say that again, to use it, be sure to use the --out FILE or --outDir DIRECTORY options because if you don’t the compiler will take the input javascript file and overwrite the original with it’s compiled version.

With source control, this can potentially be a fun experiment to see what TypeScript’s version looks compared to your own, but I’ll leave that up to you to play with.

Best of luck on your port to TypeScript.

0 thoughts on “How to compile plain *.js (JavaScript) files with the TypeScript Compiler

  1. Why is it so hard to strike a balance? To be honest, I think because the barrier to entry is so low, and what people typically want these tools to do is really pretty simple, that it’s faster/easier to just write your own then to learn one of the bigger (and of course un/underdocumented) existing projects. And then you need a few more features, and then your friends start using it, and then there are 14 competing standards.

  2. As a .NET dev who shifted to Node/front-end work this year, I definitely feel your pain.

    However, I think it’s mitigated some due to the fact that there are usually only a few real choices for any category of ‘widget’ you need, especially if you want something stable and proven.

    Example: We’ve recently started using Webpack (and have a Gulp-esque config file from hell). Webpack uses third-party loaders and plugins for just about everything. However, for any given need that I’ve had, there haven’t been more than a couple of options I need to evaluate. So. while we have a dozen or so node modules just for Webpack, the mental load of choosing which of those to use is actually quite small.

Leave a Reply

Your email address will not be published. Required fields are marked *

Proudly powered by WordPress | Theme: Code Blog by Crimson Themes.