Writing better Typescript for MDA with XrmDefinitelyTyped

Javascript is dead - long live Typescript. After you have read this post, you will actually like developing client-side logic for Model-driven apps. This post will assume that you have...

Latest Post Writing better Typescript for MDA with XrmDefinitelyTyped by Magnus Gether Sørensen

Javascript is dead - long live Typescript. After you have read this post, you will actually like developing client-side logic for Model-driven apps.

This post will assume that you have some knowledge of Typescript in relation to Javascript. If you do not, then the Typescript website is a great start https://www.typescriptlang.org/index.html

If you have experience with writing Typescript for MDA, then you have probably installed the @types/xrm typings at some point. These provide generic typings for the form context and the global Xrm namespace.

My problem with those typings is that they are generic. If you use those typings, you would still be writing magic strings when trying to get attributes or controls. You would not know if the attributes you are trying to get from the form will actually exist on the form. This is fixed by XrmDefinitelyTyped. It analyses your forms and generate specific typings for each form as well as the typings for the global Xrm namespace.

By casting the form context to the form of your choice, you will only be able to interact with fields that are on that form.

Typings for the main Account form "Firma"

This means you no longer have to remember the logicalnames of fields on your form. This makes you catch more errors during compile-time instead of catching them at run-time. You also no longer have to remember the type of value that is returned. In the above example we can see that address1_city is of type string.

In addition to this, XrmDefinitelyTyped adds support for strongly-typed Web API calls through XrmQuery. You can perform CRUD operations, and some additional requests. XrmQuery supports the standard .then syntax, but it looks much better with a promise callback so you can make your code cleaner with async/await.

Fetching related contacts for the account

In this example we make a RetrieveMultiple request for contact and select fullname and creditlimit and filter based on the current record Id. As a result of the generated typings, it will only be able to select attributes that exists on the contact entity. Looking at the filter, it compares the GUID string to the GUID of the current record. If one was to put a number in the filter it would fail, since the generated typings include attribute type. Thus, it is only possible to compare apples to apples.

Notice because we only select fullname and creditlimit the resulting type only includes those fields. This ensures that you can only use the values that you actually retrieve, which further prevents run-time errors.

If XrmQuery does not have a strongly typed version of your request yet, you can use the sendRequest function to make a generic request. Here is an example of calling a workflow using async/await.

Example of using XrmQuery to send a Execute Workflow request using the Web API

Compared to the well-known approach of using XmlHttpRequests, this is much cleaner, less error-prone and enables the use of promises.

A final note for the ones that like the generality of Javascript, those that like to reuse and follow DRY. All client-side code in a MDA runs in the context of a form. Therefore, it only makes sense to bind that code to the form. If your code runs in multiple forms, then XrmDefinitelyTyped can create typings for the intersection of those forms.

This allows you to write generic type-safe code. If you want to read more about that then look at the wiki for the tool https://github.com/delegateas/XrmDefinitelyTyped/wiki/Form-intersections

Stay tuned for in-depth examples of how I use XrmDefinitelyTyped to write early-bound Typescript for Dynamics 365.

Magnus Gether Sørensen

Published 4 months ago