CSS Sticky Position

Before going any further, this is supposed by Chrome 56+ and not many browser yet. The actual Chrome stable version is 56, hence it should be used with a good fallback.

Sticky position is a new CSS position that allow to have a sticky element that is not sticky all the time. This is different from fixed which place an HTML element in a place and never move. With position to sticky, you define a threshold where the element will change from relative to “fixed”.

To illustrate, image a list that has a lot of element and once in a while you have title that you want to stick for the section. When scrolling, you want the title to unstick when you reach a new section. Every active section should have its own title fixed at the top. This can be achieved by JavaScript or now with Sticky. Here is a simple example of CSS that is applied to a class name “list-header” which should be used in each of section’s title.

.list-header { 
    position: sticky; 
    top: 5px; 
}

Every time the user scroll down, if the title reach the top by 5px (so not already touching the top but almost) the sticky get away until a new title reach the top. Normally, you want a very small number because otherwise, it will start getting sticky too early. In the example above, you would see a 5px game between the top of the title and the top of the container. A top of 1 or -1 would make more sense because the title would be almost flush to the top of the container.

You can see an example (inspired by Mozilla’s documentation) here : https://codepen.io/mrdesjardins/pen/RpwLMy which will produce this output:

Visual Studio Code with NPM and TypeScript (Part 7 : watcher & auto-refresh)

Developing website front-end gives some habit to have a fast preview of the modification we do in the code. Mostly because HTML, CSS and JavaScript at the base doesn’t require any compilation. Simply saving the file and refreshing the browser was enough to see the new code working in the browser. However, with TypeScript, we need to compile to have a new release of the output JavaScript. To do so, we need something to watch all TypeScript files, compile and refresh the browser.

This basic example is not very optimized for a big code base because this new Gulp task will watch all TypeScript file and if one change, will rebuild every TypeScript. In a more enterprise scenario or big project, we would have smarter watch to work on branch of the code which would result to a fast build of file or section who need to get updated.

Creating a task is done like usual. The trick is to have a dependent task at the “gulp.watch”. This watch doesn’t require any dependency to npm package, it’s there with Gulp. It takes file pattern to know which files to look for changes and an array of other task to do when something change.

gulp.task('watch', function() {
    gulp.watch(paths.typescript_in + '/*.ts', ['build']);
});

The next step is to have the browser reload itself automatically. We were using ExpressJs, but we will use something else from that point. We will use gulp-connect. It’s a very light-weight server with live reload integrated.

npm install gulp-connect --save-dev

We can delete the server.js file we had before and add the following gulp task into gulpfile.js

gulp.task('watch', function() {
    gulp.watch(paths.typescript_in + '/*.ts', ['build']);
});

gulp.task('server', function() {
  connect.server({
    root: 'output',
    livereload: true,
    port: 8080
  });
});

gulp.task('go', ["server", "watch"], function() {

});

We also need to do two changes to actual task. The first one is once we are done building TypeScript, we notify the connector to reload. The second one is to move the index.html, boot page, in the output folder since we will run the server from this server.

gulp.task("build", function () {
   //...
        .pipe(connect.reload());
});

and

gulp.task("copy", function () {
   //...
     gulp.src("./src/index.html").pipe(gulp.dest(paths.typescript_out));
});

From that point, anytime we run the server, by executing : gulp go, the server will execute and wait for any changes since we have a dependency to watch who is looking for changes to compile. Once compilation is over, the connect call reload which is using a websocket to communicate to the webpage to reload.

You can find the whole source code in GitHub : https://github.com/MrDesjardins/TypescriptNpmGulp

Delegating Consuming Task into WebWorker

Heavy operation can hang the main thread in JavaScript. This is mainly because there is only a single thread and every operation needs to not be too much intensive. A way to handle an heavy operation is to delegate this one into a WebWorker.

A WebWorker is a place in the browser that can be requested by a page to do some task without being executed into the main thread. It has some limitations, like not being able to manipulate the Dom and being more slow, but has the main advantage to not interfere the main thread. All is done by messages between the script from the page and the script that run the worker.

To illustrate the benefit, we will use an intensive script that will be run in the main thread from one button and having a second button that execute the same script into the WebWorker. The main thread will have the time updating every 50ms as well as adding a dot. The first button will have the consequence of having the time and the dot to stop for few seconds, while the WebWorker will have always a smooth time and dot update. Here is the result of the code being executed in the main thread.

As you can see, when the button is click, the heavy process is taking so much of the processor that it hangs the whole thread. The clock stops ticking, the dots stop moving. However, looks at the result with WebWorker.

The animation keeps working with the dots and the clock is not interfered by calculation. At the end, it’s more smooth because the main thread is not doing the heavy lifting — the WebWorker is doing it.

The whole project is built in TypeSript which compile everything into JavaScript. The whole code can be found in this GitHub repository: https://github.com/MrDesjardins/TypeScriptWebWorker

The project contains 3 files. The main.ts which will create the two buttons and starts the timer for the clock and the dots. The algo.ts which contains an intensive, not efficient, way to calculate prime numbers. It has two parameters, the first is the number of iteration and the second a multiplier. The iteration is to find more than just one prime number, the multiplier is increasing with a random number a number to verify if it’s a prime.

The slow button is executing the following code that disable the button, instantiate the algorithm class and execute it with a huge number. When it returns, it says that the data is back and enable the button.

function slowFunction(): void {
    $("#btn1").prop("disabled", true);
    const algo = new Algorithm();
    const result = algo.calculatePrimes(50, 99887766554);
    const $line = $("<p>").append("Result is returned");
    $("#main").append($line);
    $("#btn1").prop("disabled", false);
}

The WebWorker button is doing something different and needs more code. To execute code in the WebWorker we need to load the WebWorker and pass a message. To Receive the value back to the page from the WebWorker, we need to subscribe to an event.

let worker: Worker;
const callBack = (message: MessageEvent) => {
    if (message.data.command === "done") {
        const result =  message.data.prime;
        const $line = $("<p>").append("Result is returned");
        $("#main").append($line);
    }
    $("#btn2").prop("disabled", false);
};
function slowFunctionWebWorker(): void {
    $("#btn2").prop("disabled", true);
    if (worker) {
        worker.removeEventListener("message", callBack);
        worker.terminate();
    }
    worker = new Worker("output/webworker.js");
    worker.addEventListener("message", callBack, false);

    setTimeout(() => {
        worker.postMessage({
            multiplier: 50,
            iterations: 50000,
        });
    }, 1000);
}

The call back, is looking for which message is sent back. The string could have been anything, the important is that the WebWorker needs to send the same. This is the way to handle multiple messages and response between the page and WebWorker. In our case, we have only one method and one response so a single string is the only thing required which is called “done”.

The button is disabled and make sure that if a previous worker existed to remove the response listener and termine this one. After, it creates the worker. This is done by using the Worker class and passing a relative path to the WebWorker JavaScript file. After, we need to subscribe to a worker which of type “message”. This allows to pass messages between the page and the WebWorker. Finally, there is a timeout of 1 sec before passing the request command down. The reason is that we need some time to the WebWorker to instanciate and register to listen to command. As you can see the postMessage is the way to call the WebWorker with some arguments.

The WebWorker is using the same algorithm that the one execute in the main script which was loading it from an other module. To do that with WebWorker, we need to get more barebone which mean we cannot use the import syntax, but directly use requirejs.

importScripts("../vendors/requirejs/require.js");
console.log("loaded");
requirejs.config({
    baseUrl: ".",
});
require(["algo"], function (algo_1) {
    console.log("required");
    //debugger;
    self.addEventListener("message", (message: MessageEvent) => {
        console.log("receive message begin");
        const origin = message.origin;
        const iterations = message.data.iterations;
        const multiplier = message.data.multiplier;
        const algo = new algo_1.Algorithm();
        const result = algo.calculatePrimes(iterations, multiplier);
        console.log("receive message end");
        (self as any).postMessage({
            command: "done",
            primes: result
        });
    });
});

To load a script, we must use “importScripts” which will let us having requirejs to load the module. Then, we need to configure RequireJs with a minimum configuration. Then, we call require to load the algo module. A good thing is that you can use console.log as well as the debugger keyword to debug the WebWorker. Next, you need to subscribe to the “message” event to be able to receive the postMessage from the webpage. Once we receive a message, we get the parameters, instantiate the algorithm class and wait the result. Once the result is out, we postMessage back to the page. I had to cast to “any” to have access to postMessage (there is probably a better way).

The end result is way better and as you can see, the interface doesn’t pay the price. However, if you have keen eyes, you also saw that I reduced the multiplier count from 99 887 766 554 to 50 000. That is a lot less! Why? Because keeping the same huge value was killing the WebWorker. By that, I mean that the algorithm was running forever. The whole process was running more slowly than the main thread for an unknown reason to me (at this time I am writing this post). I’ll have a future post about why it’s slower, but for the moment, if you need to have some telemetry task, or small task that block the UI just for more than few seconds (but not too much!), it may be worth it to move some logic down to a WebWorker. Also, as you can see, TypeScript is totally possible with WebWorker without a lot of hassle which is a big plus for anyone working with TypeScript project.

Visual Studio Code with NPM and TypeScript (Part 6 : Lazy-loading)

To have the fastest website possible you must be wise to not load unnecessary JavaScript. In some scenario, it is the good strategy to not have everything in a bundle. For example, if a kind of action require different JavaScript files but that this one is not in the main scenario then it’s better to lazy-load this module. This article will explain how to lazy-load TypeScript module.

Let’s fake the scenario that we want to load a module 2 seconds after a method is called:

export class ClassB {
    public method1(): void {
        console.log("ClassB>method1");
        setTimeout(() => {
           //Use code from fileToLazyLoad.ts
        }, 2000);
    }
}

The way to do it is to use directly the AMD loader instead of using the EcmaScript import. This might not be the case in the future, but this is how to do it at the time I am writing this post. From the previous article about TypeScript, we configured to use AMD (requirejs). To have the TypeScript lazy-loaded, we will need to use require directly in the file. The first step is to add at the top of the file a require to a reference to the type. This won’t load the file at runtime, but let us in development time a reference to the type. The second step is to use requirejs() method at the time you need to module. The third step is to have the types aware in every modules. This last and third step is done by using :

npm install @types/requirejs --save-dev

The first and second step can be seen in this transformed code form the initial snippet:

import foo = require("folder1/fileToLazyLoad");
export class ClassB {
    public method1(): void {
        console.log("ClassB>method1");
        setTimeout(() => {
            requirejs(["folder1/fileToLazyLoad"], (c: typeof foo) => {
                const co = new c.ClassC();
                co.method1();
            });
        }, 2000);
    }
}

You can see that you can load multiple modules since the first parameter is an array. The second is a function that contains the same amount of argument that the length of the array. It’s at this moment that the browser will do a HTTP request to get JavaScript file and execute the code. In that example, the method1() is called once the file is downloaded.

Here is how the browser handles the HTTP request:

Lazy loading should be in your tool belt and be used anytime you can delay unnecessary module on the critical path. Good case are for dialog window, or deep hidden menu options. However, be careful not to degrade the user experience by having the user to wait on every click. Nothing is more annoying than clicking a menu and having a white space for few milliseconds. While not everything needs to be loaded, once the user is having what needed to work, you should eagerly load alternate scenario. At the end, the best strategy is to use lazy-loading at the right moment to have a good balance of performance and user experience.

TypeScript Object Spread Property

If you see three little dots, you saw the object spread property. This property allows to do many different operations, like the Rest one. It allows you to do merge of objects, to do shallow copy of objects, transform an array into multiple fields of an object, be used as function arguments to allow array or to assign values to an array.

Shallow Copy

If you want to have a copy of all values but a different object, you can use the spread operator.

const user = {
    firstName: "Patrick",
    lastName : "Desjardins",
    isMarried: true
};
const shallowCopy = { ...user };

This will create a copy. It means that if you compare user to shallowCopy (triple equal), it won’t be the same object.

Merge

One of the very interesting feature of the spread operator is the capability to merge object. To do the merge, you need to create a new variable that will get assigned by a new object (curly braces) that will take the spread operator followed by the name of the object. Then, a comma with the spread operator and the second object. The new object will get all fields of the first object followed by the second object. If the second object has the same fields has the first one, then this one will override the value.

const defaultUser = {
    firstName: "NotDefined",
    lastName: "NotDefined",
    hasPaid: false
};

const user = {
    firstName: "Patrick",
    isMarried: true
};
const finalUser = { ...defaultUser , ...user };

In this example, the final user first name is “Patrick”, the last name is “NotDefined” and the “hasPaid” is false. Also, it contains the field set in the second object that wasn’t set in the first one “isMarried” to “true”. Like the shallow copy, this is shallow which mean that if you are limited to the object and not object of object. For example, if user has an array of object for the dependents that he may have, the list of dependencies won’t get merged.

Array to object

This is a shortcut to the well known trick of using apply to pass an array of parameter to a function that takes parameters. Instead of using yourFunction.apply(this, yourList) you can use yourFunction(…yourList).

function yourFunction(x:number, y:number, z:number): void { 
 //Use variable x, y and z.
}
var args:number[] = [0, 1, 2];
yourFunction(...args);

Function Parameter

In the same way of “array to object” works, you can directly use the spread operator in the parameter. This is done by using the spread operator in front of the name of the parameter. This allow to pass parameter which will be stored into an array automatically.

function yourFunction(...x: number[]) { 
 console.log(JSON.stringify(x));
}
yourFunction(1, 2, 3);

Destructuring

This is a good scenario where you know some inputs but want to also take all other inputs that the user set into a subsequent array. For example, you know that the user can pass an array where the first parameter is the unique identifier, followed by a modified date and all other data will be new values to add. You could use the following code to have an array of data to add and two variables to manipulate into a query to save new data.

var [id, date, ...valuesToAdd] = [1, 2, 3, 4];
console.log(id === 1); //true
console.log(date === 2); //true
console.log(valuesToAdd[0] === 3); //true
console.log(valuesToAdd[1] === 4); //true

We could replace var [id, date, …valuesToAdd] = [1, 2, 3, 4]; by var [id, date, …valuesToAdd] = anotherArray; and anotherArray wouldn’t be affected by the operation.

Assign values to array

This could also be called merging array. You take a first array, by adding it as an element with the spread operator inside the square bracket of the new array. This array element with the spread operator will transform all values of this array and make it like if you were using every values of this one as parameter.

var list = [1, 2];
var list2 = [...list, 3, 4];
console.log(list); // [1,2]
console.log(list2); // [1,2,3,4]

In this article we saw how you can use the spread property into multiple scenarios. Like any new language features, it’s always important to know when to use it and to not abuse it.

Visual Studio Code with NPM and TypeScript (Part 5 : TsLint)

Code needs to have some consistency to be able to have a uniform reading later. When your code grows and the number of software developers, it becomes harder to handle it manually. TsLint is a TypeScript linter who is a code analyzer that gives which line needs improvement in term of code readability, maintainability, and functionality errors. TsLint is configurable for your own preferences and can be executed manually, automatically when writing code or as a step in your continuous integration process.

To install TsLint, you need to install the TsLint npm package:

npm install -g tslint typescript --savedev
npm install gulp-tslint --savedev

You have to create a configuration file “tslint.json” at the root of your project. The position of this file is the same as the tsconfig.json or typings.json or gulpfile.js file.

In this file, you can configure the rules you want. A basic configuration is to extend an existing one and override some properties to your taste.

{
  /*
   * Possible values:
   * - the name of a built-in config
   * - the name of an NPM module which has a "main" file that exports a config object
   * - a relative path to a JSON file
   */
  "extends": "tslint:latest",
  "rules": {
    /*
     * Any rules specified here will override those from the base config we are extending.
     */
    "curly": true,
    "triple-equals": true
  },
  "jsRules": {
    /*
     * Any rules specified here will override those from the base config we are extending.
     */
    "curly": true
  },
  "rulesDirectory": [
    /*
     * A list of relative or absolute paths to directories that contain custom rules.
     * See the Custom Rules documentation below for more details.
     */
  ]
}

In the example above, we extend “latest”. You can read the configuration in their official GitHub:
https://github.com/palantir/tslint/tree/master/src/configs

If we want to have the rule to be executed, we need to use TsLint extension for VsCode.

At this point, you may have to reboot VsCode to have the extension to be executed when you type in Visual Studio Code. Once restarted, you should see :

The green lines indicate that the import is missing a semi-colon, that the var should be let/const and that a triple equals should be used.

Next step, is to have a Gulp task that can be executed. It can be a good idea to have this task ran automatically with your task that will build, run test, lint code. To do so, we need to use the gulp-tslint module.

const gulp_tslint = require('gulp-tslint');

The task needs to get all TypeScript files, but skip definition files and node_modules.

gulp.task('tslint', () => {
    return gulp.src(['**/*.ts', '!**/*.d.ts', '!node_modules/**'])
      .pipe(gulp_tslint())
      .pipe(gulp_tslint.report());
});

To use, in the console use : gulp tslint and you will get a report that looks like below:

[20:08:53] Using gulpfile D:\code\tsWithCode1\gulpfile.js
[20:08:53] Starting 'tslint'...
D:/code/tsWithCode1/src/file1.ts[7, 2]: file should end with a newline
D:/code/tsWithCode1/src/file1.ts[4, 1]: Forbidden 'var' keyword, use 'let' or 'const' instead
D:/code/tsWithCode1/src/file1.ts[1, 41]: Missing semicolon
D:/code/tsWithCode1/src/file1.ts[5, 7]: == should be ===

D:/code/tsWithCode1/src/fileToInclude.ts[9, 2]: file should end with a newline
D:/code/tsWithCode1/src/fileToInclude.ts[4, 9]: Calls to 'console.log' are not allowed.
D:/code/tsWithCode1/src/fileToInclude.ts[3, 5]: misplaced opening brace
D:/code/tsWithCode1/src/fileToInclude.ts[5, 13]: Identifier 'div' is never reassigned; use 'const' instead of 'let'.

From this point, you can increase the amount of rules and have a more rigid code or less depending of your need. Do not forget to add into your repository the configuration to be sure that everyone of the team uses the same rules.

TypeScript and Object Rest a.k.a. destructuring

There is a lot of synonym around Rest and Spread. The Rest/Spread specification talk about object properties, Mozilla documents it under expressions and operators with the title destructuring assignment. I personaly like just calling it “spread” and don’t like the “rest” part since it’s share the name of Rest Api which make it hard to find good result on Internet. However, regardless of the name, let’s explore this object Rest experimental functionalities of JavaScript/EcmaScript, already present if you are using TypeScript.

Object Rest a.k.a. destructuring

They are more than one usage for Rest. You can extract object’s fields into individual variables, take the remaining of the field into an object, copy array values into variable, swapping value between variables, take the remaining of the values of an array into a new array.

Extracting Object fields a.k.a. Object Destructuring Assignment

Imagine that you have an object and that you want to extract specific values. A common scenario could be that you get more data from a Rest Api call and you need to get specific values.

const user = {
    id: 1,
    name: "Patrick Desjardins",
    website: "https://patrickdesjardins.com/blog",
    isPaidUser: false,
    email: "patrick@email.com
};

Traditionally, you would do :

const id = user.id;
const name = user.name;
const email = user.email;

Now, with object destructuring assigment you can extract in a single line the field you want.

const {id, name, email} = user;

This operation doesn’t alter the user variable and create 3 variables that can be accessed like the traditional way.

The example shown set the value from the name of the user. However, we can also specify the name of the variable we want which can be handy if the schema returned from the Rest Api doesn’t satisfy the convention you are using. Let’s do an example where we change the name to have underscore in front of each variable that we extract.

const {id:_id, name:_name, email:_email} = user;

We can also have some cases where the information you get may not contain the property desired. For example, the user may have a field numberOfChildren with an integer if this one has at least one child and return nothing if no children. In that case, we would want to have a default value to 0.

const {id, name, email, numberOfChildren=0} = user;

In the case that the user has numberOfChildren defined, this one will take over the default value. In all cases, we can be sure that numberOfChildren variable will be set with a value.

Take the remaining of the field into an object

As seen in the previous section, you can extract specific fields into variable. But, you can also store all the remaining fields into a new object.

const {id, email, ...allRemainingFields} = user;

The value of allRemainingFields is an anonymous (any) object with the field email, website, isPaidUser.

Copy array values into variable

This scenario is handy if you accept an array for parameter and needs to extract values by position. For example, you expect to receive an array of 3 elements and that you want to store these 3 elements in a variable.

const myArray = ["patrick", "desjardins", true];
const [firstName, lastName, hasPaid] = myArray;

You probably ask yourself about what if the array doesn’t contain at least 3 items that won’t work! Well, you can also use default value. Here is an example where the website was not passed in the array.

const myArray = ["patrick", "desjardins", true];
const [firstName, lastName, hasPaid, website="none"] = myArray;

Swapping value between variables

Maybe not as useful but still interesting to have in your tool belt is two swap value between two variables. Doing it manually requires to have a temporary variable. You take the value of var1 set it to tempo, take value of var2 set it to var1 and set var2 with tempo.

let var1 = 100;
let var2 = 300;
let tempo;

tempo = var1;
var1 = var2;
var2 = tempo;

Now, you can do it in a single line without temporary variable.

let var1 = 100;
let var2 = 300;
[var1, var2] = [var2, var1];

Take the remaining of the values of an array into a new array

This is similar to what we did with object’s fields, but this time with an array. We can set some array values into variables and the remaining into a new array.

const myArray = ["patrick", "desjardins", true];
const [firstName, ...remaining];

In this example remaining is : [“desjardins”, true]

We saw a lot of different scenario where destructuring could be interesting by avoiding several lines of code for simple object or array manipulation. In an upcoming article we will see about the second operator called spread and how this one can simplify even more your JavaScript/TypeScript code.

Visual Studio Code with NPM and TypeScript (Part 4 : Node Server)

So far, in this series, we have used TypeScript and Gulp but didn’t executed in a browser any code. This time, we will look about how to launch a small HTTP server with node.js.

Many solutions exist, but we will go with Express.

npm install --save express 

The next step is to create a file that nodejs will use as entry point to use Express. You can name it the name you want, in this example, we will call it server.js. The first step, a little bit like Gulp worked in the previous step, we need to require the library. The next code is to start listening to a specific port.

var express = require('express')
var app = express()

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.use(express.static('.'))

app.listen(3000, function () {
  console.log('Server listening on port 3000.')
})

To be able to server our static file, the index.html, we need to use the static file and point the folder. Since we have index.html at the root, we can just use dot. Ideally, we would move the whole file structure into a single folder and not server all our configuration file, but for the moment, let’s keep it this way.

At that point, you can start the server in a Powershell console simply by using nodejs and the file we just created.

node server.js

You should see in the console “Server listening on port 3000.” which is the console.log from the listen method. You can go in a browser and write : http://localhost:3000/index.html

Compiling Individual TypeScript File with VSCode

TypeScript is used to compile TypeScript .ts into JavaScript .js. The basic setup is to have a tsconfig.json file that indicate what file to include, and which files to exclude. Almost everyone is having a Gulp/Grunt task that will execute the compilation, some goes a step ahead with having a watcher that looks for changes to start compiling. The problem is when a project grows, it doesn’t make sense in term of efficiency to build every TypeScript when only one change.

The first step is to make a new Gulp’s task that will look similar to this one which, at this moment, hard code a single file to be compiled.

const gulp = require('gulp');
const tsc = require('gulp-typescript');
const tsProject = tsc.createProject('tsconfig.json');

gulp.task("buildsinglefile", () => {
    const pathWithFileNameToCompile = "src/folder1/file2.ts";
    const pathWithoutFileNameForOutput = "./output/folder1";
    return gulp.src(pathWithFileNameToCompile)
        .pipe(tsc({
            "target": "es6",
            "module": "amd"
        }))
        .pipe(gulp.dest(pathWithoutFileNameForOutput));
});

As you can see from the 2 first lines, it needs to have 2 npm packages.

npm install gulp --save-savedev
npm install gulp-typescript typescript --save-savedev
npm install gulp-sourcemaps --save-dev

The Gulp’s script needs to take in parameter some information from Visual Studio Code. To pass this data, we need VSCode to sent its variable through arguments

{
    "version": "0.1.0",
    "command": "gulp",
    "isShellCommand": true,
    "args": [
        "--workspaceRoot",
        "${workspaceRoot}",
        "--fileDirname",
        "${fileDirname}",
        "--file",
        "${file}"
    ],
    "tasks": [
        {
            "taskName": "buildsinglefile",
            "isBuildCommand": true,
            "args": []
        }
    ]
}

To make it works, we need to pass the double dash for the name of the parameter, followed by special macro variable of VSCode. Then, the Gulp’s task needs to consume the argument. The arguments passed are indexed and contains more than only what is passed down by the VSCode’s task. The index 0 is the node.exe path, index 1 is the gulp.js path, index 2 starts to be out own argument, which in our case will contain “–workspaceroot” and so on. The index 7 is the first argument used and it contains the file on which the task is executed. We need it to give the file to TypeScript to compile. Next, we use argument 5 and 3 to create the output path. This need to be custom to your file structure. In the illustrated case we have a structure that looks like:
./src/same-structure-after that is compiled to ./output/same-structure-after.

gulp.task("buildsinglefile", () => {
    const arguments = process.argv;
    const pathWithFileNameToCompile = arguments[7];
    const pathWithoutFileNameForOutput = arguments[5].replace(arguments[3], ".").replace("\\src\\", "\\output\\");

    const step1 = gulp.src(pathWithFileNameToCompile)
        .pipe(sourcemaps.init())
        .pipe(tsc({
            "target": "es6",
            "module": "amd"
        }))

    step1.pipe(gulp.dest(pathWithoutFileNameForOutput));

    step1.dts.pipe(gulp.dest(pathWithoutFileNameForOutput));
    return step1.js
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest(pathWithoutFileNameForOutput));
});

To use it, we only need to press “F1” on the single file we want to compile, type “task”, select “Run Task” and select “buildsinglefile”.

This will generate the map file, as well as the JavaScript file. You can click the following image to see the animation of how it works.

Having a quick way to build file you are working on is crucial to move fast forward. This is one step in this direction. Two possibles improvement would be to have a shortcut to execute this task, and another solution is to have a file watcher that execute a compilation on the modified file.