192

How can I configure Visual Studio Code to compile typescript files on save?

I see it is possible to configure a task to build the file in focus using the ${file} as an argument. But I would like this to be done when a file is saved.

Linus Unnebäck
  • 23,234
  • 15
  • 74
  • 89
Powell Quiring
  • 2,349
  • 2
  • 11
  • 9

17 Answers17

248

May 2018 update:

As of May 2018 you no longer need to create tsconfig.json manually or configure task runner.

  1. Run tsc --init in your project folder to create tsconfig.json file (if you don't have one already).
  2. Press Ctrl+Shift+B to open a list of tasks in VS Code and select tsc: watch - tsconfig.json.
  3. Done! Your project is recompiled on every file save.

You can have several tsconfig.json files in your workspace and run multiple compilations at once if you want (e.g. frontend and backend separately).

Original answer:

You can do this with Build commands:

Create a simple tsconfig.json with "watch": true (this will instruct compiler to watch all compiled files):

{
    "compilerOptions": {
        "target": "es5",
        "out": "js/script.js",
        "watch": true
    }
}

Note that files array is omitted, by default all *.ts files in all subdirectories will be compiled. You can provide any other parameters or change target/out, just make sure that watch is set to true.

Configure your task (Ctrl+Shift+P -> Configure Task Runner):

{
    "version": "0.1.0",
    "command": "tsc",
    "showOutput": "silent",
    "isShellCommand": true,
    "problemMatcher": "$tsc"
}

Now press Ctrl+Shift+B to build the project. You will see compiler output in the output window (Ctrl+Shift+U).

The compiler will compile files automatically when saved. To stop the compilation, press Ctrl+P -> > Tasks: Terminate Running Task

I've created a project template specifically for this answer: typescript-node-basic

zlumer
  • 6,844
  • 1
  • 25
  • 25
  • 18
    Problem with this is it keeps a task running, VS Code knows when I save a less file, or ts file, it feels like redundant to have another watcher just because we can't hook to "On save" command easily. I wonder if someone's already done a extension to run something when specific filetype is saved, would be much better. – Ciantic Dec 31 '15 at 10:42
  • 2
    @Ciantic this answer was written before VS Code had extensions support. There's just an [extension](https://marketplace.visualstudio.com/items/emeraldwalk.RunOnSave) you're talking about, but it's actually faster to have TypeScript compiler watch files and re-compile only the changed ones. – zlumer Dec 31 '15 at 14:53
  • What is the difference between the task runner and the basic tsconfig.json ? Do you need both? tsconfig.json also includes an option "compileOnSave": true – Kokodoko Apr 05 '16 at 13:35
  • 1
    @Kokodoko bc compileOnSave only works in VS 2015, not Code – scape Apr 10 '16 at 10:37
  • 2
    @scape It works in VS Code as well, if you add "-w" to the command line arguments in tasks.json ! – Kokodoko Apr 11 '16 at 11:12
  • 1
    **Actually VSCode does the configuration stuff for you:** On `configure task`: VSCode will auto-detect that there is a `tsconfig.json` and prompt a dialog where you can choose either `tsc: build - tsconfig.json` or `tsc: watch - tsconfig.json`. Choose the latter and VSCode generates the `tasks.json` file (if there was no before) and adds the right configuration for you. – Daniel Apr 03 '18 at 02:12
  • 1
    In Addition to my comment above: The property `"watch": true` is not needed in the `tsconfig.json` file, due to the watch task. – Daniel Apr 03 '18 at 02:21
  • 1
    @zlumer My anwser https://stackoverflow.com/questions/29996145/visual-studio-code-compile-on-save/60374212#60374212 not require pressing Ctrl+Shift+B so is more user friendly. – SkorpEN Feb 24 '20 at 10:59
43

If you want to avoid having to use CTRL+SHIFT+B and instead want this to occur any time you save a file, you can bind the command to the same short-cut as the save action:

[
    {
        "key": "ctrl+s",          
        "command": "workbench.action.tasks.build" 
    }
]

This goes in your keybindings.json - (head to this using File -> Preferences -> Keyboard Shortcuts).

Fenton
  • 241,084
  • 71
  • 387
  • 401
  • 2
    This should just be an add-on to the above answer (edited). This made my day! – chrissavage Jun 10 '16 at 19:26
  • good answer... ?how to filter whats will be launched... for example: I only want to execute command if the file has html extension ??? – ZEE Jul 21 '16 at 14:20
  • @ZEE yes, this is possible, please see this bit of documentation for [keybindings](https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts) and also [httpete's answer](http://stackoverflow.com/a/34094418/4565795) for a brief example. Specifically, the `when` condition` using `editorLangId` is of import. – BobChao87 Apr 11 '17 at 01:22
  • Wont this will override the original command ? – parth_07 Dec 23 '20 at 22:46
30

If pressing Ctrl+Shift+B seems like a lot of effort, you can switch on "Auto Save" (File > Auto Save) and use NodeJS to watch all the files in your project, and run TSC automatically.

Open a Node.JS command prompt, change directory to your project root folder and type the following;

tsc -w

And hey presto, each time VS Code auto saves the file, TSC will recompile it.

This technique is mentioned in a blog post;

http://www.typescriptguy.com/getting-started/angularjs-typescript/

Scroll down to "Compile on save"

Jon Preece
  • 715
  • 8
  • 13
8

Write an Extension

Now that vscode is extensible, it is possible to hook into the on save event via an extension. A good overview of writing extensions for VSCode can be found here: https://code.visualstudio.com/docs/extensions/overview

Here's a simple example that just calls echo $filepath and outputs stdout in a message dialogue:

import * as vscode from 'vscode';
import {exec} from 'child_process';

export function activate(context: vscode.ExtensionContext) {

    vscode.window.showInformationMessage('Run command on save enabled.');

    var cmd = vscode.commands.registerCommand('extension.executeOnSave', () => {

        var onSave = vscode.workspace.onDidSaveTextDocument((e: vscode.TextDocument) => {

            // execute some child process on save
            var child = exec('echo ' + e.fileName);
            child.stdout.on('data', (data) => {
                vscode.window.showInformationMessage(data);
            });
        });
        context.subscriptions.push(onSave);
    });

    context.subscriptions.push(cmd);
}

(Also referenced on this SO question: https://stackoverflow.com/a/33843805/20489)

Existing VSCode Extension

If you want to just install an existing extension, here is one that I wrote available in the VSCode gallery: https://marketplace.visualstudio.com/items/emeraldwalk.RunOnSave

Source code is available here: https://github.com/emeraldwalk/vscode-runonsave/blob/master/src/extension.ts

Community
  • 1
  • 1
bingles
  • 11,582
  • 10
  • 82
  • 93
7

An extremely simple way to auto-compile upon save is to type one of the following into the terminal:

tsc main --watch // autosave `main.ts`
tsc -w // autosave all typescript files in your project

Note, this will only run as long as this terminal is open, but it's a very simple solution that can be run while you're editing a program.

Daniel C Jacobs
  • 691
  • 8
  • 18
6

I have struggled mightily to get the behavior I want. This is the easiest and best way to get TypeScript files to compile on save, to the configuration I want, only THIS file (the saved file). It's a tasks.json and a keybindings.json.

enter image description here

httpete
  • 2,765
  • 26
  • 34
  • 7
    for lazy developers: `{ "version": "0.1.0", "command": "tsc", "isShellCommand": true, "args": ["--module","amd","--target","ES5","${file}"], "showOutput": "silent", "problemMatcher": "$tsc" } ` keybingings: `{ "key": "cmd+s", "command": "workbench.action.tasks.build", "when":"editorTextFocus && editorLangId == 'typescript'" }` – Dariusz Filipiak May 07 '16 at 10:45
  • I can say with the latest version of TypeScript 1.8.X and 1.0 of Visual Studio code, the technique I showed is obsolete. Simply use a tsconfig.json at the root level of your project and all works automatically for syntax checking. Then use tsc -w on the command line for watching / recompiling automatically. { "compilerOptions": { "module": "amd", "target": "ES5", "noImplicitAny": false, "removeComments": true, "preserveConstEnums": true, "inlineSourceMap": true }, "exclude": [ "node_modules" ] } – httpete May 09 '16 at 14:07
5

Instead of building a single file and bind Ctrl+S to trigger that build I would recommend to start tsc in watch mode using the following tasks.json file:

{
    "version": "0.1.0",
    "command": "tsc",
    "isShellCommand": true,
    "args": ["-w", "-p", "."],
    "showOutput": "silent",
    "isWatching": true,
    "problemMatcher": "$tsc-watch"
}

This will once build the whole project and then rebuild the files that get saved independent of how they get saved (Ctrl+S, auto save, ...)

John Weisz
  • 30,137
  • 13
  • 89
  • 132
Dirk Bäumer
  • 1,183
  • 9
  • 7
4

In your tsconfig.json

"compileOnSave": true, // change it to true and save the application

also restart your application --> ng serve

if the problem is still there then restart your IDE / developer tool

WasiF
  • 26,101
  • 16
  • 120
  • 128
  • 1
    Does VS code nowadays support that feature? Last time when I checked, it could not save and I needed to use extension to do it. – Antti Jan 14 '19 at 20:03
  • Now it does support – WasiF Jan 15 '19 at 10:23
  • Isn't this only optional for frameworks like angular or react? In a scratched project relying on global tsc I am not sure this will work. My VSCode does not take care of this. – seedme Mar 20 '22 at 07:27
  • Nope it doesn't work, I tried your Step 3 to break my file and save it but changes in the terminal are ***not*** happening when saving the (broken) file. By the mere fact that I had to manually add your line of code inside `tsconfig.json` and it *wasn't commented out which I can remove comments and use it* is a say-so that it wouldn't work, and it doesn't. – Aleksandar Apr 26 '23 at 01:21
  • It would be nice if it was as simple as compileOnSave. I'm testing with a dirt-simple TS folder project, completely restarted VSCode, absolutely no effect from this directive. Bug? – TonyG May 31 '23 at 05:06
3

Current status of this issue:

https://github.com/Microsoft/vscode/issues/7015

Trident D'Gao
  • 18,973
  • 19
  • 95
  • 159
3

I use automatic tasks run on folder (should work VSCode >=1.30) in .vscode/tasks.json

{
 "version": "2.0.0",
 "tasks": [
    {
        "type": "typescript",
        "tsconfig": "tsconfig.json",
        "option": "watch",
        "presentation": {
            "echo": true,
            "reveal": "silent",
            "focus": false,
            "panel": "shared"
        },
        "isBackground": true,
        "runOptions": {"runOn": "folderOpen"},
        "problemMatcher": [
            "$tsc-watch"
        ],
        "group": {
            "kind": "build",
            "isDefault": true
        }
    }
 ]
}

If this still not work on project folder open try Ctrl+shift+P and Tasks: Manage Automatic Tasks in Folder and choose "Allow Automatic Tasks in folder" on main project folder or running folder.

SkorpEN
  • 2,491
  • 1
  • 22
  • 28
2

I implemented compile on save with gulp task using gulp-typescript and incremental build. This allows to control compilation whatever you want. Notice my variable tsServerProject, in my real project I also have tsClientProject because I want to compile my client code with no module specified. As I know you can't do it with vs code.

var gulp = require('gulp'),
    ts = require('gulp-typescript'),
    sourcemaps = require('gulp-sourcemaps');

var tsServerProject = ts.createProject({
   declarationFiles: false,
   noExternalResolve: false,
   module: 'commonjs',
   target: 'ES5'
});

var srcServer = 'src/server/**/*.ts'

gulp.task('watch-server', ['compile-server'], watchServer);
gulp.task('compile-server', compileServer);

function watchServer(params) {
   gulp.watch(srcServer, ['compile-server']);
}

function compileServer(params) {
   var tsResult = gulp.src(srcServer)
      .pipe(sourcemaps.init())
      .pipe(ts(tsServerProject));

   return tsResult.js
      .pipe(sourcemaps.write('./source-maps'))
      .pipe(gulp.dest('src/server/'));

}
Andzej Maciusovic
  • 4,306
  • 1
  • 29
  • 40
2

There are various valid answers here but not necessarily good for everyone per different TS compiler env. Maybe following can work globally.

Step 1

have a minimum tsconfig.json underneath your project root folder, for example,

"compilerOptions": {
      "baseUrl": "./",
      "outDir": "./dist/",
      "forceConsistentCasingInFileNames": true,
      "sourceMap": true,
      "strict": true,
      "target": "es2017",
      "module": "es2020",
}
# where you can set your outDir accordingly.

Step 2

set your current TS complier tsc to watch the project root folder. To achieve this, open another terminal tab, and run following command and leave it in the background.

$ tsc --watch --project ./
# tsc is your working compiler, may be different than this. I currently using global TyperScript Compiler to watch on save therefore tcs. Change to yours accordingly
# ref: https://www.typescriptlang.org/docs/handbook/compiler-options.html

This is more neat than rely on IDE task watcher.

When you don't need it to watch anymore, simple Ctrl/Command + C to terminate it or even close/recycle the terminal

seedme
  • 403
  • 5
  • 9
1

Select Preferences -> Workspace Settings and add the following code, If you have Hot reload enabled, then the changes reflect immediately in the browser

{
    "files.exclude": {
        "**/.git": true,
        "**/.DS_Store": true,
        "**/*.js.map": true,
        "**/*.js": {"when": "$(basename).ts"}
    },
    "files.autoSave": "afterDelay",
    "files.autoSaveDelay": 1000
}
Ignatius Andrew
  • 8,012
  • 3
  • 54
  • 54
1

I can say with the latest version of TypeScript 1.8.X and 1.0 of Visual Studio code, the technique I showed is obsolete. Simply use a tsconfig.json at the root level of your project and all works automatically for syntax checking. Then use tsc -w on the command line for watching / recompiling automatically. It will read the same tsconfig.json file for options and config of ts compile.

// tsconfig.json

{
    "compilerOptions": {
        "module": "amd",
        "target": "ES5",
        "noImplicitAny": false,
        "removeComments": true,
        "preserveConstEnums": true,
        "inlineSourceMap": true
    },
    "exclude": [ "node_modules" ]
} 
Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
httpete
  • 2,765
  • 26
  • 34
1

You need to increase the watches limit to fix the recompile issue on save, Open terminal and enter these two commands:

sudo sysctl fs.inotify.max_user_watches=524288
sudo sysctl -p --system

To make the changes persistent even after restart, run this command also:

echo fs.inotify.max_user_watches=524288 | sudo tee /etc/sysctl.d/40-max-user-watches.conf && sudo sysctl --system
Waleed Shahzaib
  • 1,526
  • 2
  • 18
  • 34
1
  1. Run tsc --init in your project folder to create tsconfig. json file (if you don't have one already)

  2. Press Ctrl+Shift+B to open a list of tasks in VS Code and select "tsc: watch - tsconfig.json"

  3. Done! Your project is recompiled on every file save.

This worked for me but for step 2 I can only select "tsc: espion - tsconfig.json" in the list of tasks (no "tsc: watch - tsconfig.json" found in the list)

bendeg
  • 196
  • 2
  • 8
0

tried the above methods but mine stopped auto-compile when it felt like it, due to maximum files to watch have passed the limit.

run cat /proc/sys/fs/inotify/max_user_watches command .

if it's showing fewer files count including node_modules then open the file /etc/sysctl.conf in root privilege and append

fs.inotify.max_user_watches=524288 into the file and save

run again the cat command to see the result. It will work! hopefully!

Aelaf
  • 118
  • 1
  • 11
  • I remember seeing this problem a couple years ago with huge projects and there was a similar solution for Windows. Does anyone have that? I think it applied to PHP as well as TS/JS and other languages. If required I'll see if I can dig it up. – TonyG May 31 '23 at 05:12