Using TypeScript for Visual Studio Online Extensions

The new VSO extensibility model needs extensions to have a webserver today for hosting content like pages, javascript and css files and images. This webserver can be IIS, Node.js or something else. We are thinking to add an option in the future to host content inside VSO where the extension developers will not need to setup a website and they will provide a package which will contain all the content required by the UI integration. This will be especially helpful for integrations like menu actions where a javascript file is enough for action handlers (like this one).

However, no matter a website or a package is used for an extension, communication with the host is through javascript. There may be some extensions which do not require host communication like displaying a static page inside a hub but this scenario is out of the subject of this post.

The only thing needs to be done for communication is adding a reference for VSS.SDK.js to the page. This lets an extension:

  1. initialize VSS.SDK for communication
  2. register an action handler
  3. get notified when the page is ready (to talk to host)
  4. get context information about the host or extension
  5. use host services like dialog or history
  6. use a UI control provided by the host
  7. make a rest call to VSO for build, work, code, etc.

Starting from M82 (release notes), we generate a TypeScript declare file VSS.d.ts which will significantly improve the development experience if you use TypeScript (and we encourage you to do so). This declare file not only contains types for above listed communication steps but also for UI Controls and Rest Clients provided by VSO.

Once you add the below reference to the top of the TypeScript file, you should be good to go.

  /// <reference path='../typings/VSS' />

Please note that, you should also have jquery.d.ts, knockout.d.ts and q.d.ts right next to VSS.d.ts since some of the classes and interfaces rely on these libraries. You can find them either here or in DefinitelyTyped repo.

Then you’ll get the intellisense for VSS module.

vss-intellisense

Declarations for UI Controls and Rest Clients

As mentioned before, VSS.d.ts contains types for both UI Controls and Rest Clients. However, they are different than SDK types. VSO uses  Asynchronous Module Definition (AMD) for loading javascript files and in order to use UI Controls and Rest Clients which requires the host to be instructed to setup module loader first using below code snippet. This will add necessary VSO styles and javascript files to the extension page and configure AMD loader.

  VSS.init({
    setupModuleLoader: true 
 });

The rest is about adding necessary require statement and start using UI controls or Rest Clients. Here is a sample for our grid:

 import Controls = require("VSS/Controls");
import Grids = require("VSS/Controls/Grids");

var container = $(".my-container");
var gridOptions: Grids.IGridOptions = {
    height: "300px",
    width: "100%",
    source: function () {
        var result = [], i;
        for (i = 0; i < 100; i++) {
            result[result.length] = [i, "Column 2 text" + i, "Column 3 " + Math.random()];
        }

        return result;
    } (),
    columns: [
        { text: "Column 1", index: 0, width: 50 },
        { text: "Column 2", index: 1, width: 200, canSortBy: false },
        { text: "Column 3", index: 2, width: 450 }]
};

var grid = Controls.create<Grids.Grid, Grids.IGridOptions>(Grids.Grid, container, gridOptions);

Here is a sample for a Rest Client which gets the list of projects from the account where extension is hosted:

 import Service = require("VSS/Service");
import Core_Contracts = require("TFS/Core/Contracts");
import Core_Client = require("TFS/Core/RestClient");
import WebApi_Constants = require("VSS/WebApi/Constants");

var client = Service.VssConnection
    .getConnection()
    .getHttpClient(Core_Client.CoreHttpClient, WebApi_Constants.ServiceInstanceTypes.TFS);

    client.getProjects().then((projects: Core_Contracts.TeamProjectReference[]) => {
    for (var p of projects) {
        console.log(`Project name: ${p.name}, project id: ${p.id}, state: ${p.state}`);
    }
 });

How about Documentation?

We are working hard to add reference and samples for our client libraries. We do not have anything yet for SDK and UI Controls but added Reference for Rest Clients recently. Even Rest Client reference has a lot of missing doc but we are filling the gaps. We are also expecting to add doc and samples for SDK and UI Controls really soon.

Let us know if you have any feedback here.