BlazorTS 1.7.0.60
dotnet add package BlazorTS --version 1.7.0.60
NuGet\Install-Package BlazorTS -Version 1.7.0.60
<PackageReference Include="BlazorTS" Version="1.7.0.60" />
<PackageVersion Include="BlazorTS" Version="1.7.0.60" />
<PackageReference Include="BlazorTS" />
paket add BlazorTS --version 1.7.0.60
#r "nuget: BlazorTS, 1.7.0.60"
#:package BlazorTS@1.7.0.60
#addin nuget:?package=BlazorTS&version=1.7.0.60
#tool nuget:?package=BlazorTS&version=1.7.0.60
BlazorTS
🚀 A tool for seamless Blazor-TypeScript integration
<div align="center">
</div>
BlazorTS is a source generator library that uses Tree-sitter syntax tree parsing to analyze TypeScript code and automatically generate strongly typed C# wrappers, allowing Blazor applications to call TypeScript functions directly without hand-written JavaScript interop glue.
✨ Features
- 🔄 Compile-time generation: Analyze TypeScript files and generate C# wrappers automatically
- 🎯 Type safety: Strongly typed C# APIs for exported TypeScript functions
- 🚀 Zero configuration: Minimal setup, works out of the box
- 🔧 Automatic registration: Generated interop services are registered through
AddBlazorTSScripts() - 🌳 Precise parsing: Uses Tree-sitter for accurate TypeScript syntax handling
📦 Installation
Core Libraries
| NuGet Package | Description |
|---|---|
BlazorTS |
Core runtime library |
BlazorTS.SourceGenerator |
Source generator library |
BlazorTS.Assets |
Asset management with dynamic URLs |
Microsoft.TypeScript.MSBuild |
TypeScript compilation support |
Installation and Configuration
dotnet add package BlazorTS
dotnet add package BlazorTS.SourceGenerator
dotnet add package BlazorTS.Assets # optional
dotnet add package Microsoft.TypeScript.MSBuild # optional
<ItemGroup>
<AdditionalFiles Include="**/*.razor.ts" Exclude="**/node_modules/**" />
<AdditionalFiles Include="**/*.entry.ts" Exclude="**/node_modules/**" />
</ItemGroup>
🚀 File Naming Conventions
1. Razor Component Scripts (.razor.ts)
These files are bound to a specific Razor component.
- Naming:
MyComponent.razor.tsmust pair withMyComponent.razor - Generated output:
- a
partial classfor the component - a top-level
*TSInteropservice for that component - an auto-injected
Scriptsproperty on the component
- a
- Usage: call exported TypeScript functions through the generated
Scriptsproperty
Example
// Components/Pages/Counter.razor.ts
export function increment(count: number): number {
return count + 1;
}
@page "/counter"
@code {
private int currentCount = 0;
private async Task HandleClick()
{
currentCount = await Scripts.increment(currentCount);
}
}
Conceptually, BlazorTS generates code like this:
public partial class Counter
{
[Inject] public CounterTSInterop Scripts { get; set; } = null!;
}
public class CounterTSInterop(ScriptBridge invoker)
{
private readonly string url = invoker.ResolveNS("MyApp.Components.Pages.Counter", ".razor");
public async Task<double> increment(double count)
{
return await invoker.InvokeAsync<double>(url, "increment", new object?[] { count });
}
}
2. Standalone Feature Modules (.entry.ts)
These files define reusable TypeScript modules that can be injected as services.
- Naming:
my-utils.entry.tsorapi.entry.ts - Generated output: a normal C# service class
- Usage: register with
AddBlazorTSScripts()and inject where needed
// Services/Formatter.entry.ts
export function formatCurrency(amount: number): string {
return `$${amount.toFixed(2)}`;
}
builder.Services.AddBlazorTSScripts();
@inject TestApp.Services.Formatter Formatter
<p>@await Formatter.formatCurrency(123.45)</p>
Configure tsconfig.json
{
"compilerOptions": {
"noImplicitAny": false,
"noEmitOnError": true,
"removeComments": false,
"target": "es2015",
"rootDir": ".",
"outDir": "wwwroot/js"
},
"include": [
"**/*.razor.ts",
"**/*.entry.ts"
]
}
Register Services
using BlazorTS.SourceGenerator.Extensions;
builder.Services.AddBlazorTS();
builder.Services.AddBlazorTSScripts();
🛠️ Custom Path Resolution
By default, BlazorTS maps a logical component or module name to /js/....
builder.Services.AddBlazorTS((type, suffix) =>
{
var path = type.FullName!.Replace('.', '/');
return $"/scripts/{path}{suffix}.js";
});
public class CustomResolver : INSResolver
{
public string ResolveNS(Type tsType, string suffix)
{
var path = tsType.FullName!.Replace('.', '/');
return $"/lib/{path}{suffix}.js";
}
public string ResolveNS(string fullName, string suffix)
{
var path = fullName.Replace('.', '/');
return $"/lib/{path}{suffix}.js";
}
}
builder.Services.AddBlazorTS<CustomResolver>();
Suffix Parameter
- Razor components (
.razor.ts) use suffix".razor" - Entry modules (
.entry.ts) use suffix".entry" - Other module styles can use any custom suffix
🔧 Supported Types
| TypeScript | C# Parameter | Return Type |
|---|---|---|
string |
string |
Task<string> |
number |
double |
Task<double> |
boolean |
bool |
Task<bool> |
any |
object? |
Task<object?> |
void |
- | Task |
Promise<T> |
- | Task<T> |
Real Blazor Regression Coverage
The repository now includes a minimal real Blazor app at BlazorTS.RealBlazorApp/ to validate behavior beyond Roslyn-only generator tests.
BlazorTS.RealBlazorApp/: a minimal real Blazor Web App that keeps only the files required for interop verificationBlazorTS.RealBlazorApp/Components/Pages/GenericProbe.razor: a real generic Razor componentBlazorTS.RealBlazorApp/Components/Pages/GenericProbe.razor.ts: the paired script that generates the top-levelGenericProbeTSInteropBlazorTS.RealBlazorApp.Tests/: regression tests that assert the finalized model through reflection, DI registration, and real compiled artifacts
This project specifically covers:
- generic parameters stay on the component partial class
Scriptsauto-injection still works in a real Razor compilation flow- interop services remain top-level non-generic
*TSInteroptypes AddBlazorTSScripts()registers the generated interop type for DI
📖 Documentation
🤝 Contributing
Issues and Pull Requests are welcome.
📄 License
MIT License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Microsoft.AspNetCore.Components.Web (>= 9.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.7.0.60 | 97 | 3/10/2026 |
| 1.6.2.56 | 313 | 9/19/2025 |
| 1.6.1.54 | 326 | 9/16/2025 |
| 1.5.1.50 | 165 | 9/14/2025 |
| 1.5.0.48 | 160 | 9/14/2025 |
| 1.4.2.46 | 128 | 9/12/2025 |
| 1.4.1.44 | 138 | 9/12/2025 |
| 1.4.0.38 | 189 | 9/11/2025 |
| 1.3.0.34 | 194 | 9/10/2025 |
| 1.2.10.32 | 206 | 9/8/2025 |
| 1.2.9.29 | 192 | 9/8/2025 |
| 1.2.8.28 | 182 | 9/8/2025 |
| 1.2.3.26 | 183 | 9/8/2025 |
| 1.2.2.24 | 221 | 8/29/2025 |
| 1.2.1.21 | 226 | 8/29/2025 |
| 1.0.9.13 | 246 | 8/28/2025 |
| 1.0.8.10 | 233 | 8/28/2025 |
| 1.0.7.9 | 231 | 8/28/2025 |
| 1.0.6.8 | 228 | 8/28/2025 |
| 1.0.5.7 | 245 | 8/28/2025 |
基于 TypeScriptParser 和 Tree-sitter 的 Blazor TypeScript 互操作框架