If you write code to SQL Server then you might be interested in this: I have written a tSQLt tdd training course which has helped over 500 people learn both tSQLt and how to apply TDD practices to their SQL Server T-SQL development, you can join the course at https://courses.agilesql.club.

VSTS extensions, mixing VSS.require and import ... require

I have been starting to write more and more typescript lately and quite enjoying it. I have also been writing a few vsts extensions and using typescript to write vsts extensions seems to be working quite nicely. One of the best things, for me, about typescript is to use type information which gives compile time verification and intellisense.

This is good but when it comes to VSTS extensions, almost every sample I have seen follows this pattern:

VSS.require(['ReleaseManagement/Core/RestClient'], (RmClientService) => { //do something with RmClientService }

What happens here is that vsts provides the RmClientService, you then do something with it. The RmClientService is (forgive my lack of typescript here) a pointer to the module that is defined as ‘ReleaseManagement/Core/RestClient’ in the vss web SDK.

VSS.require has to be used. If you just did a require(‘ReleaseManagement/Core/RestClient’) then the reference you get back won’t have been initialized in vsts.

VSS.require doesn’t actually import a module anyway there is no way (that I know of) to add type information to RmClientService.

If you find the RmClientService definition it looks like:

declare module "ReleaseManagement/Core/RestClient" { import Contracts = require("ReleaseManagement/Core/Contracts"); import VSS_FormInput_Contracts = require("VSS/Common/Contracts/FormInput"); import VSS_WebApi = require("VSS/WebApi/RestClient"); ... /** * Gets an http client targeting the latest released version of the APIs. * * @return ReleaseHttpClient4 */ export function getClient(options?: VSS_WebApi.IVssHttpClientOptions): ReleaseHttpClient4; }

Because this is a module and not a type we can’t declare the type on RmClientService but we can define the type that is returned by getClient().

So, in our code, once we call getClient we know the type that we expect but VSS.require doesn’t import any type information so we can fall back to a separate require which we can use, just purely for type information:

import RmContractDefintitions = require("ReleaseManagement/Core/Contracts"); import RmClientDefinitions = require('ReleaseManagement/Core/RestClient');

So by using the type information from the plain require and the actual objects returned from VSS.require we can get full type information including compile-time checking and intellisense:

import RmContractDefintitions = require("ReleaseManagement/Core/Contracts"); import RmClientDefinitions = require('ReleaseManagement/Core/RestClient'); ...

VSS.require([‘ReleaseManagement/Core/RestClient’], (RmClientService) => {

let rmClient : RmClientDefinitions.ReleaseHttpClient4 = RmClientService.getClient();

This compared to no types and no intellisense:

Obviously, this code won’t be found to be wrong until a pull publish, reload cycle which could be minutes depending on the type of extension.

Subscribe

* indicates required

Please select all the ways you would like to hear from Agile Sql Club:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.