Blazor and TypeScript

In the past I wrote a blog post on Blazor and the JavaScript interop. but what about TypeScript, I mean it obviously transpiles to JavaScript, so we should be able to use it, right ?

So yes, we can easily use TypeScript within a Blazor application, let’s do the following

  • Create a Blazor WebAssembly Standalone App (you can use the server one’s if you prefer, but for this post that’s the template I’m starting with)
  • Add the NuGet Package Microsoft.TypeScript.MSBuild, this will allow us to transpile our TypeSript code as part of the build process. This will add the following to the csproj (the version may differ ofcourse)
    <PackageReference Include="Microsoft.TypeScript.MSBuild" Version="5.7.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    
  • Within the project root, i.e. where Program.cs is located, add a file tsconfig.json, mine looks like this
    {
      "compilerOptions": {
        "module": "ES2015",
        "target": "ES2024",
        "sourceMap": true
      },
      "exclude": [
        "node_modules"
      ]
    }
    
  • Let’s create a scripts folder off of wwwroot
  • Now create a file, mine’s not very imaginatively named Example.ts and here’s the code
    namespace Example {
        export class Prompt {
            public showAlert(message: string): string {
                return prompt(message, "Hey");
            }
        }
    }
    
    export function getPromptInstance(): Example.Prompt {
        return new Example.Prompt();
    }
    

Before we look at using this code let’s just review a few of the steps.

The tsconfig.json if, ofcourse, used to configure the TypeScript transpiler. The module and target do NOT need to be these two values, but we do need to use a module type which will generate an export function. Some of the other module types will not include the export definition and then we cannot access the factory method getPromptInstance. So feel free to change these two options but before your JavaScript needs to export our factory function.

As mentioned, we’re using the getPromptInstance to create an instance to our class, ofcourse we could export more functions and remove the class in this example.

Interop from Blazor

Interop. with our transpiled code uses the same mechanism/code as my old post Blazor and the JavaScript interop., but let’s create some code in this sample anyway.

Let’s do the following

  • Add a Button to the Home.razor page that looks like this
    <button class="btn btn-primary" @onclick="DisplayMessage">Alert me</button>
    
  • Now add a code block which looks like this
    @code{
        private async Task DisplayMessage()
        {
            var module = await JsRuntime.InvokeAsync<IJSObjectReference>("import", "./scripts/Example.js");
            var o = await module.InvokeAsync<IJSObjectReference>("getPromptInstance");
            await o.InvokeVoidAsync("showAlert", "Hello TypeScript World");
        }
    }
    
  • We also need to add the following to the top of the Home.razore file, below the @page line
    @inject IJSRuntime JsRuntime
    

Now when you run the application you’ll see the “Alert me” button, clicking this will load the script (note we reference the .js script here obviously) and then we get a reference to the getPromptInstance function and call the showAlert method of the previously defined TypeScript class.

Obviously you’ll probably prefer to create a new C# class that holds onto a reference to the imported script, but hopefully this post gives you a starting point to porting/using TypeScript code within your Blazor app.

Code for this post is available at GitHub