One of the most exciting prospects of Blazor is the potential to remove the need for JavaScript. However, we are not there yet. In an earlier post, I pointed out that WebAssembly isn’t currently able to interact with the DOM or call browser APIs. I’m not even sure how server-side Blazor is going to move away from JavaScript or if it can.

So if we’re going to have to write JavaScript, then it would be great to get as close to our development experience with C# as we can. This is where we can leverage TypeScript.

TypeScript is a first class citizen in Visual Studio, one of the benefits of this is that any TypeScript you write in your Blazor project will be transpiled to JS for you automatically.

But what about TypeScript in a Razor Class Library project? Unfortunately, this doesn’t get compiled automatically. It turns out though that it’s not too difficult to get this working.

What is TypeScript

Just before we continue, for those who aren’t familiar, TypeScript is a typed superset of JavaScript, which compiles to plain JavaScript. It gives us the ability to use static typing, classes and interfaces. But the biggest benefit is that because it’s compiled, we can get compile time checks on our code as apposed to writing plain JS where errors may only show up at runtime.

The Example

For this post we’re going to use the standard Razor Class Library template. You can create this via the dotnet CLI using the following command.

dotnet new razorclasslib

Inside this project there is a content folder with a file called exampleJsInterop.js, with the following contents.

// This is a JavaScript module that is loaded on demand. It can export any number of
// functions, and may import other JavaScript modules if required.

export function showPrompt(message) {
  return prompt(message, 'Type anything here');
}

We’re going to convert this file to TypeScript and then make a few changes to the project to make it compile when the project builds.

Converting to TypeScript

As I mentioned earlier, TypeScript is a superset of JavaScript what this means is that any valid JavaScript is valid TypeScript. So we could just give the exampleJsInterop file a .ts extension and we would be done. But that kind of defeats the point of using TypeScript.

So we’re going to rewrite the code to take advantage of some of the features TypeScript gives us.

namespace JSInteropWithTypeScript {

  class ExampleJsFunctions {
    public showPrompt(message: string): string {
      return prompt(message, 'Type anything here');
    }
  }

  export function Load(): void {
    window['exampleJsFunctions'] = new ExampleJsFunctions();
  }
}

JSInteropWithTypeScript.Load();

This is how things look once converted to TypeScript. Hopefully, this should look a lot more familiar to C# developers. We now have a namespace, a class and types. I’ll admit that types don’t really give us much as this code is going to be called by C#. But if the showPrompt method was going to be called by another TypeScript method we would now benefit from compile time checks.

Configuring the build

We now have our TypeScript file so how can we get it to build with our project. The first thing we need to do is to install the [Microsoft.TypeScript.MSBuild](https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild) package from NuGet. You can do this either via the NuGet package manger.

Install-Package Microsoft.TypeScript.MSBuild

Or via the dotnet CLI.

dotnet add package Microsoft.TypeScript.MSBuild

Once installed, we need to add a tsconfig.json to the root of the Razor Class Library project. Below is an example of a basic config.

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "sourceMap": true
  },
  "exclude": [
    "node_modules"
  ]
}

Checking the build

That should be all we need to be able to compile our TypeScript. We can now do a build and if everything has gone to plan then you should see a exampleJsInterop.js file and a exampleJsInterop.js.map file.

The .map file has been generated for us by the TypeScript compiler. Map files provide a mapping between the original TypeScript source file and the compiled JavaScript. This means we can debug the TypeScript version of our code in the browser instead of the compiled JavaScript version.

Summary

In this post, we’ve taken a first look at how we can use TypeScript with our Blazor libraries. As well as how we can configure our projects to compile our TypeScript files during a build.

There is a lot more that can be done with TypeScript in terms of configuration but I wanted to provide a quick start guide which should work for most interop cases in Blazor. Have you written much interop code so far? Let me know in the comments.