D365 Typescript Web Resources - Part 2 - Type Declarations

Before you get stuck into this make sure you’ve checked out any previous parts to the series.

Type Declarations for the D365/XRM Client API

What are they?

A declaration file provides a way to declare the existence of some types or values without actually providing implementations for those values.

Read more about them here and here

Do we need to construct our own?

Short answer: No

Long answer: No, but you may want to extend either of the two I’ll mention below.

Longer answer: No, but you may want to extend either of the two I’ll mention below, and you may even want to author you own.

So what do we have available?

Personally I have had a play with both @types/xrm and delegateas/XrmDefinitelyTyped

Of the two I prefer XrmDefinitelyTyped as it extends on @types/xrm by providing CrmSvcUtil like functionality to build Typescript interfaces that represent the entities and forms within your D365CE environment.

For the purpose of this post we’ll take a look at XrmDefinitelyTyped :-)

Install XrmDefinitelyTyped

XrmDefinitelyTyped is packaged via Nuget so you’ll need to ensure you have Nuget installed. Just download the latest nuget.exe into the root of you workspace.

Oh, you can download a starter workspace based on part 1 of this series from here

  • Once you’ve installed Nuget run the following from the root of the workspace…
    1
    nuget.exe install Delegate.XrmDefinitelyTyped -OutputDirectory .\
  • Next we need to configure XrmDefinitelyTyped. Within the XrmDefinitelyTyped directory you should find XrmDefinitelyTyped.exe.config. We are going to need provide some values for the settings in here.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
    <appSettings>
    <add key="out" value="./typings/XRM" />
    <add key="solutions" value="" />
    <add key="entities" value="account, contact" />
    <add key="web" value="WebApiEntities" />
    <add key="jsLib" value="./src/lib" />
    <add key="mfaAppId" value="" />
    <add key="mfaReturnUrl" value=""/>
    </appSettings>
    </configuration>
    Alternatively you can use command line switches. I tend to use a combination of the two. Providing a list of the entities in the config file but the connection settings via the command line.
    1
    XrmDefinitelyTyped.exe /url:https://<organizationName>.crm<regionNumber>.dynamics.com/XRMServices/2011/Organization.svc /username:<username> /password:<password> /useconfig:.\Delegate.XrmDefinitelyTyped.5.1.6\content\XrmDefinitelyTyped\XrmDefinitelyTyped.exe.config

make sure to check the version number of XrmDefinitelyTyped used in the /useconfig: command line switch

  • Update the tsconfig.json with a reference to our new declarations by adding the typings to the include.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    {
    "compilerOptions": {
    "module": "ES6",
    "noImplicitAny": false,
    "removeComments": true,
    "preserveConstEnums": true,
    "outDir": "dist",
    "sourceMap": true
    },
    "include": [
    "src/**/*",
    "typings/**/*"
    ],
    "exclude": [
    "node_modules",
    "**/*.spec.ts",
    "dist"
    ]
    }

Note we also have to turn noImplicitAny off

And that’s it. XDT (XrmDefinitelyTyped) should now be installed and ready to reference within your Typescript. As with CrmSvcUtil you will need to run XrmDefinitelyTyped.exe each time you need to update your typings with any customisation changes you have made to your entities, forms, etc.

Typing your types in your Typescript ;-)

Easy, and C# devs will love it!
Remember our first ts file we created in part 1

1
2
3
4
5
6
class ContactMainForm {
static OnLoad(executionContext: any) {
const formContext = executionContext.getFormContext();
formContext.ui.setFormNotification("Typescript locked and loaded!", "INFO", "ts-msg");
}
}

Lets apply some typings to our objects…

1
2
3
4
5
6
class ContactMainForm {
static OnLoad(executionContext: Xrm.ExecutionContext<Form.contact.Main.Contact, any>) {
const formContext = executionContext.getFormContext() as Form.contact.Main.Contact;
formContext.ui.setFormNotification("Typescript locked and loaded!", "INFO", "ts-msg");
}
}

Now, what I love about XDT is the type inference, for example getting an attribute infers the type depending on the logical name and you get something a little like this when writing your code:

For example the parentcustomerid attribute type is Xrm.LookupAttribute<"account" | "contact"> and the getValue() function returns a EntityReference<"account" | "contact">[]. Anyway I think you get the point.

Remember F12 in your IDE will link you to the definition in the typescript declaration :-)

That’s all folks!

I hope that helps you get XDT working in your project. Please use the comments below, i’m more than happy to take questions and extend this post with any suggestions I feel would be of value.

You can download a copy of the source code for this blog post here

Thanks for reading.
Ollie