TypeScript has been on my radar and I decided to finally take some time to understand more about it and whether or not it has a place inside Dynamics 365.

What is TypeScript?

Typescript is a strongly typed scalable superset of JavaScript developed and maintained by Microsoft. It allows a more declarative style of programming over JavaScript with the use of interfaces, static typing and tooling. TypeScript is a transpiler which means it essentially converts one language into another, in this case, TypeScript to JavaScript.

Why use TypeScript over JavaScript in Dynamics 365?

I think most can agree that when it comes to many projects the messiest part of the solution is the JS web resources that are written. In terms of readability and maintainability, traditional JavaScript in D365 has it flaws. Being loosely typed, small typo’s can lead to wasted time and energy looking through hundreds of lines of code for something as measly as an incorrectly placed uppercase letter. The lack of Intellisense becomes frustrating and more importantly I find so much disorganisation when it comes to a true object orientated design within the JavaScript files.

TypeScript introduces an optional type for JavaScript, meaning increased agility when doing refactoring and provides compile time safety for your JavaScript code assisting with type safety. TypeScript is pure object oriented with classes, interfaces and statically typed like C# or Java.

What’s most important for me, is that with TypeScript I can now write my JavaScript in a C# manner while enjoying Intellisense including type definitions for the Microsoft Dynamics xRM API and have transpiler take care of what the JavaScript will look like.

Demonstration

I am going to create a new TypeScript solution in Visual Studio 2017 which will add some functionality to the contact entity in Dynamics 365.

Prerequisites

Let’s start off by creating a blank solution in Visual Studio named Xrm.Scripts

Next, we want to create a new ASP.NET Empty Web Site within this solution named Scripts.

Visual Studio will add some additional files and folders but we can remove these and simply create two folders named Javascript and Typescript.

We will need to add a new TypeScript JSON Configuration File to the solution. This will tell the compiler where to place the generated JS files as well as some additional settings. By default, the compiler would place the generated JS files in the same folder as the TS files. I prefer to keep these separated in their respective folders.

The supporting documentation on the config file is found here (https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)

For now, we will simply set the file as follows:

 

{
  "compileOnSave": true,
  "compilerOptions": {
    "noImplicitAny": false,
    "noEmitOnError": true,
    "outDir": "Javascript",
    "removeComments": false,
    "sourceMap": true,
    "target": "es5"
  },
  "include": [
    "./Typescript/**/*"
  ]
}

 

Notably above, we have set the outDir which tells the directory which folder to place the JS files into and we have set the include which tells the compiler to include all files in the Typescript folder. We have also added compileOnSave which signals to the IDE to generate all files for a given tsconfig.json upon saving.

Now we need to add two TypeScript files named ContactLibrary.ts and EntityLibrary.cs

ContactLibrary will contain an onload event to demonstrate a call to a class and the EntityLibrary will contain a class and method to demonstrate OOP within the files.

Before we continue to the code for these to files, I mentioned earlier the benefit of Intellisense on the XRM API. To reap this benefit, we will need to add a type script definition to the solution for the Xrm API.  Browsing to www.definitelytyped.org you have a repository for many TypeScript Definitions, so it is no surprise that you would find the definition for XRM here. From this repository if you click TypeSearch on the top navigation menu you can search for Xrm.

There are few ways to install an NPM package in Visual Studio but my preferred method is using a some extension named Package Installer. (https://marketplace.visualstudio.com/items?itemName=MadsKristensen.PackageInstaller)

Once installed, right click the project and click Quick Install Package, select npm and type  @types/xrm.

Once the installation is complete you will have a few additional files and folders added to the solution.

Xrm Intellisense!

Next, we want to add the following code the ContactLibrary.ts file:

/// <reference path="../node_modules/@types/xrm/index.d.ts" />
namespace CRMProject.Contact {

    //Common Class
    export class ContactCommon {

        public getCrmUrl() {
            let url = Xrm.Page.context.getClientUrl();
            alert(url);
        }

        public setFirstName(firstName: string) {
            Xrm.Page.getAttribute("firstname").setValue(firstName);
        }
    }

    //Form Functions
    export function onLoad() {

        //alert the client url
        let cmnLib = new ContactCommon();
        cmnLib.getCrmUrl();
    }

    export function onSave() {

        //create a duplicate contact
        let firstName = Xrm.Page.getAttribute("firstname").getValue();
        let lastName = Xrm.Page.getAttribute("lastname").getValue();

        let contact = new Entity.Contact(firstName, lastName);
        contact.createNew();
    }
}

And the following code to the EntityLibrary.ts file:

/// <reference path="../node_modules/@types/xrm/index.d.ts" />
namespace CRMProject.Entity {

    export class Contact {

        public firstName: string;
        public lastName: string;

        public constructor(firstName: string, lastName: string) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public createNew() {
            let contactData =
            {
                "firstname": this.firstName,
                "lastname": this.lastName
            }
            Xrm.WebApi.createRecord("contact", contactData).then(
                function success(result) {
                    alert("Duplicate contact created");
                },
                function (error) {
                    alert(error.message);
                }
            );
        }
    }

}

As you save the solution and refresh the Solution Explorer you will notice the newly generated JS files within the Javascript folder. As far as TypeScript goes, there are various syntax’s in the language which need to be learnt but what’s important here is how the transpiler is generating the JS files in the all familiar JS syntax. Now we have a strongly typed class which is far more readable and scalable in the form of a TS file which is converted to JS for deployment to D365.

Finally, we can manually deploy the generated JS files to a solution within D365 and plug them into the onSave (CRMProject.Contact.onSave) and onLoad (CRMProject.Contact.onLoad) events of the contact form.

When we load the contact form, the onsave is triggered and in this case the crm url is alerted

When we save the record, a duplicate is created by first and last name

Conclusion

I am certainly going to be implementing TypeScript in my solutions going forward. The benefit of Intellisense, C# like language, full OOP support and the scalability of TypeScript is far too large and beneficial to ignore.

The solution is available for download at https://www.dropbox.com/s/y7vy1abqszxdmbj/Typescript%20Demo.zip?dl=0

Happy Coding!

Please follow and like us:
0

Leave a Reply

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