Using TypeScript for your VSTS extension walk trough

One of my targets of this year was to start writing TypeScript and experience the usability compared to my experience writing javascript over 20 years ago. My weapon of choice to write build and release extensions have always been PowerShell and it has always gotten the job done. Until recently I wanted to expose more clearly to a team a “state” a release pipeline is in, more about this topic in the near future. But this forced me to start thinking towards TypeScript to expose the information like an hub inside the VSTS Release hub.

The first thing I experienced was that the documentation about this topic is kind of scattered and you need to keep in mind that there are multiple ways and versions to achieve it. This cost me a lot of time because packages and transpilations didn’t always work like I expected. Which resulted in the idea to write a blog about this topic to help people kickstart writing the extension.


If you want the working example just get them from my git repo here. And enter npm install ,  tsc -p .  .Change the  "publisher": "publisher name",  to your publisher name and enter  tfx extension create --rev-version  and publish your extension to your VSTS.
Or you can use the  generator-vsts-extension  here, developed by the Alm Rangers.

Getting ready

To get started you’ll need:

  • A VSTS account if you haven’t got one you can start here
  • A text editor. I used and love Visual Studio Code, and you can download it for free here
  • The latest version of node which can be found here

Getting the environment ready

Fire up Visual Studio Code and open a new folder let’s call it home, make sure to use only lowercase. This will make the npm setup easier later on. Inside home we are going to create the following project structure:

You can achieve this by running the following commands from your project root directory home in the “Integrated Terminal” window Ctrl+~.

Getting dependencies and configuration ready

To manage the dependencies we use npm which was installed during the node installation. There are different ways to install the dependencies depending on the use by your project. During this walktrough we use the --save for the packages your code is dependent on during run-time. And we use  --save-dev for the packages dependent on during compile time. Run the following statements in the “Integrated Terminal” window in the project root directory home.

Next we need to tell the typescript how to use our code and where to find the type definitions of the extension we want to use. So change the settings in the tsconfig.json to resemble these:

Now we can compile our code using tsc -p . this will create a dist/index.js.

To publish the extension to VSTS we first need to package it. Therefor we installed the tfx-cli. This will take care of that, after we correctly entered the manifest in the vss-extension.json. A few interesting parts of the manifest are the scopes . Through them you can manage the permissions of your application it needs to run. You can find the full list here. Another tricky setting which took me long to figure out was the "includes": ["ms.vss-releaseManagement-web.release-service-data-external"], which is needed on top of the scopes for the release management rest API.

Setting up the index.html

To create an index.html in the static folder we need 3 things:

  • A VSS.init()
  • some containers to show the data we are going to load
  • VSS.require() where we tell to call our index.js and load some data trough the API.

Write your typescript to query the REST API.

The reason you want to write extensions is to interact with the already available data from VSTS. Therefor we have the REST API’s who we can query. First we need to get the restclient for the specific API, then we can query it and put the result json on screen or in any other UI Control you want.

Before we create the UI you can add the following code to you index.ts . It will allow your typings to be recognized in your IDE and give a basic function I used to show the queried json on screen. When you have other libraries or you didn’t set them in your tsconfig.json under "types: [""]" . You can always reference to them by adding the reference like this /// <reference types="vss-web-extension-sdk" /> on the top of your index.ts

The code below are some helper functions.

Next you can query the API and show the JSON on screen for example:
To get all builds of your project:

Some specific workitems:

The json on screen gives you an idea of the data available to work with. But it doesn’t look that nice does it? So now we can try to get all the release definition data and show it in a grid on screen.

When you compile your typescript tsc -p . . Remember that even though you can experience compilation errors your .js will always be build and you can try anyhow.

Create your package to publish

Before we can package the extension we need to replace the static\images\logo.png  with a nice picture for your extension. In the vss-extension.json  you need to set the "publisher": "PublisherName" to the same name you registered with. Now your code is ready for your first publish you need to run the tfx extension create  you can add the --rev-version  to auto increment your version number. Upload it to your marketplace account and share it with your vsts account.

When you now go to your manage extensions tab you should see the “First extension” and when you click on it you can install it.

Confirm the permissions and check your out you extension in the release tab. Out of the box this should work and any problems you can debug using F12 in your browser.

All that remains is your own creativity to get a great idea, program it and release it to everybody to enjoy. When you are trough the pain of setting up you typscript config I really like the typescript experience compared to the direct javascript but that is for everybody to decide.

Here is the Git repo I used.
Here you can find the Extension Manifest References
Here you can find the Rest Client documentation

Have fun coding!

Leave a Reply

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