Everyday TypeScript
Classes, generics, unions, decorators, modules, async/await, and modern type-system features are supported across SharpTS workflows.
A TypeScript interpreter and AOT compiler for .NET
Run it as a script for instant feedback, or compile it to a native .NET assembly — with full access to the .NET ecosystem.
curl -fsSL https://sharpts.dev/setup.sh | shirm https://sharpts.dev/setup.ps1 | iex// Run TypeScript directly on .NET
interface Greeter {
greet(name: string): string;
}
class WelcomeBot implements Greeter {
constructor(private prefix: string) {}
greet(name: string): string {
return `${this.prefix}, ${name}! Welcome to SharpTS.`;
}
}
const bot = new WelcomeBot("Hello");
console.log(bot.greet("Developer"));
// → Hello, Developer! Welcome to SharpTS.Write TypeScript that runs on the .NET runtime — interpreted for quick iteration, or compiled to native .NET assemblies.
Point SharpTS at a .ts file and it runs — no build step, no config. Ideal for scripts, automation, and trying ideas in the REPL.
Ahead-of-time compile to a real .NET assembly — a DLL, a self-contained executable, or a NuGet package — running at native CLR speed.
Call .NET libraries from TypeScript with @DotNetType, and use your compiled TypeScript from C#. Reuse the BCL, NuGet packages, and code you already have.
Use familiar TypeScript — generics, classes, decorators, async, modules, and more — with types checked before your code runs. See the practical compatibility overview below.
Drop the SharpTS.Sdk into a .NET project and dotnet build compiles your TypeScript alongside your C# — same toolchain, same output.
A language server brings autocomplete, type checking, and go-to-definition to VS Code and Visual Studio.
Real TypeScript running on the .NET runtime
const greeting: string = "Hello from SharpTS!";
const version: number = 1.0;
console.log(`${greeting} v${version}`);
const languages = ["TypeScript", "C#", ".NET"];
languages.forEach(lang => console.log(` ✓ ${lang}`));Hello from SharpTS! v1 ✓ TypeScript ✓ C# ✓ .NET
interface Comparable<T> { compareTo(other: T): number; }
class Temperature implements Comparable<Temperature> {
constructor(private celsius: number) {}
get fahrenheit(): number { return this.celsius * 9 / 5 + 32; }
compareTo(other: Temperature): number { return this.celsius - other.celsius; }
toString(): string { return `${this.celsius}°C (${this.fahrenheit}°F)`; }
}
const temps = [new Temperature(100), new Temperature(0), new Temperature(37)];
temps.sort((a, b) => a.compareTo(b));
temps.forEach(t => console.log(t.toString()));0°C (32°F) 37°C (98.6°F) 100°C (212°F)
async function delay(ms: number): Promise<string> { return `Done after ${ms}ms`; }
async function main() {
console.log(await delay(100));
const all = await Promise.all([delay(50), delay(100), delay(150)]);
all.forEach(result => console.log(result));
}
main();Done after 100ms Done after 50ms Done after 100ms Done after 150ms
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const result = data.filter(n => n % 2 === 0).map(n => n ** 2).reduce((sum, n) => sum + n, 0);
console.log(`Sum of squares of evens: ${result}`);
const [first, second, ...rest] = data;
console.log(`First: ${first}, Second: ${second}`);
console.log(`Rest: [${rest.join(", ")}]`);Sum of squares of evens: 220 First: 1, Second: 2 Rest: [3, 4, 5, 6, 7, 8, 9, 10]
console.log(`PI = ${Math.PI}`);
console.log(`E = ${Math.E}`);
console.log(`sqrt(144) = ${Math.sqrt(144)}`);
const now = new Date("2026-03-02T12:00:00.000Z");
console.log(`ISO: ${now.toISOString()}`);
const obj = { name: "SharpTS", nums: [1, 2, 3] };
console.log(`JSON: ${JSON.stringify(obj)}`);PI = 3.141592653589793
E = 2.718281828459045
sqrt(144) = 12
ISO: 2026-03-02T12:00:00.000Z
JSON: {"name":"SharpTS","nums":[1,2,3]}// Full CLI interop (the public playground intentionally disables module loading)
@DotNetType("System.Text.StringBuilder")
declare class StringBuilder {
constructor();
append(value: string): StringBuilder;
toString(): string;
}
@DotNetType("System.TimeSpan")
declare class TimeSpan {
static fromHours(value: number): TimeSpan;
readonly totalMinutes: number;
}
const sb = new StringBuilder();
sb.append("1.5 hours = ");
sb.append(`${TimeSpan.fromHours(1.5).totalMinutes} minutes`);
console.log(sb.toString());1.5 hours = 90 minutes
Concrete situations where TypeScript on .NET beats reaching for Node — or for C#.
Write build scripts, dev tools, and one-off automation in TypeScript with the whole BCL available — on machines that already have the .NET SDK and no Node toolchain. No package.json, no build step: point sharpts at the file.
sharpts rotate-logs.tsCompile a TypeScript module to a real assembly and publish it as a versioned NuGet package. With a reference assembly, C# callers instantiate your classes and call your methods fully typed.
sharpts --compile pricing.ts --ref-asm
sharpts --compile pricing.ts --packLet TypeScript-first teammates contribute in the language they know best. With SharpTS.Sdk, their .ts files build inside the same dotnet build as the C# projects around them — one toolchain, one CI pipeline.
<Project Sdk="SharpTS.Sdk/1.0.0">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<SharpTSEntryPoint>src/main.ts</SharpTSEntryPoint>
</PropertyGroup>
</Project>Compile to a single self-contained executable that runs without a separate runtime install — no Node on the target machine, no node_modules folder shipped next to your tool.
sharpts --compile tool.ts -t exe
./toolA multi-stage pipeline from source to execution
Write TypeScript and run it on .NET — right in your browser
A practical overview of the TypeScript and runtime surface you can use today. For measured detail, explore Conformance.
Classes, generics, unions, decorators, modules, async/await, and modern type-system features are supported across SharpTS workflows.
Common Array, String, collection, Promise, Date, RegExp, JSON, Symbol, and typed-array APIs are available.
Bare imports and package exports/imports can resolve, but packages still depend on SharpTS-compatible syntax and runtime APIs. TypeScript-source packages are the strongest fit.
Proxy and WeakRef are not implemented. Interpreter and AOT results can also differ on specification edge cases.
The questions that come up first — answered straight.
tsc type-checks your code and emits JavaScript for an engine like Node to run. SharpTS never produces JavaScript: it type-checks the same TypeScript, then either executes it directly or compiles it to a .NET assembly. There is no Node anywhere in the chain. The setup script uses the .NET SDK when available or installs a self-contained build when it is not.
Those projects run plain, untyped JavaScript inside a .NET host — a great fit for small embedded scripts. SharpTS runs TypeScript itself, type-checked before execution, and adds what an embedded JS engine can't: ahead-of-time compilation to IL, NuGet packaging, and typed interop in both directions between TypeScript and C#.
Partially. Bare imports resolve through node_modules, and supported module-resolution modes can apply package exports/imports and conditional targets. Packages can still fail when they rely on unsupported syntax, native add-ons, browser globals, or missing runtime APIs. Packages that ship TypeScript source are the strongest fit.
See the Node.js compatibility tracker →Each mode answers differently. The interpreter is a tree-walker tuned for instant startup — right for scripts and the REPL, not for number crunching. Compiled mode emits IL that the CLR JIT-compiles like any C# assembly, so it runs as native .NET code. In both modes, types are checked up front and then erased — they cost nothing at runtime.
It's a young, MIT-licensed project under active development. The compatibility overview above summarizes common capabilities, measured Conformance publishes the detailed evidence, and STATUS.md tracks implementation gaps.
Follow progress in STATUS.md →Up and running in three steps
Run the setup script to install the best SharpTS build for this machine
curl -fsSL https://sharpts.dev/setup.sh | shirm https://sharpts.dev/setup.ps1 | iexCreate a TypeScript file
interface Config {
name: string;
debug: boolean;
}
const config: Config = { name: "MyApp", debug: true };
console.log(`Starting ${config.name}...`);Interpret directly or compile to a .NET assembly
# Interpret (instant startup)
sharpts hello.ts
# Compile to .NET assembly
sharpts --compile hello.ts -o hello