A TypeScript interpreter and ahead-of-time compiler written in C#.
SharpTS is an implementation of a TypeScript interpreter and compiler. It implements the complete pipeline from source code to execution:
- Lexical Analysis - Tokenizing source code
- Parsing - Building an Abstract Syntax Tree
- Type Checking - Static type validation
- Execution - Either interpretation or compilation to .NET IL
SharpTS supports two execution modes:
- Interpretation - Tree-walking execution for rapid development
- AOT Compilation - Compile TypeScript to native .NET assemblies
- Types:
string,number,boolean,null,any,void,unknown,never - Generics: Generic functions, classes, and interfaces with type constraints
- Advanced Types: Union (
|), intersection (&), tuples, literal types - Arrays: Typed arrays with
push,pop,map,filter,reduce,forEach, etc. - Objects: Object literals with structural typing
- Classes: Constructors, methods, fields, inheritance,
super, static members - Abstract Classes: Abstract classes and abstract methods
- Interfaces: Structural type checking (duck typing)
- Functions: First-class functions, arrow functions, closures, default parameters
- Async/Await: Full
async/awaitwithPromise<T>and combinators (all,race,any) - Modules: ES6
import/exportwith default, named, and namespace imports - Decorators: Legacy and TC39 Stage 3 decorators with Reflect metadata API
- Control Flow:
if/else,while,do-while,for,for...of,for...in,switch - Error Handling:
try/catch/finally,throw - Operators:
??,?.,?:,instanceof,typeof, bitwise operators - Destructuring: Array/object destructuring with rest patterns
- Built-ins:
console.log,Math,Date,Map,Set,RegExp,bigint,Symbol, string methods
- Static type checking with helpful error messages
- Nominal typing for classes, structural typing for interfaces
- Compile to standalone executables or .NET assemblies
- Reference assembly output for C# interop (
--ref-asm) - IL verification (
--verify)
- Use .NET types from TypeScript via
@DotNetTypedecorator - Access BCL classes like
StringBuilder,Guid,DateTime,TimeSpan - Automatic type conversion and overload resolution
- Compile TypeScript for C# consumption with reflection or direct reference
- .NET 10 SDK or later (required)
- Visual Studio 2026 18.0+ or Visual Studio Code (optional, for IDE support)
Note for MSBuild SDK users: SharpTS.Sdk requires .NET 10 SDK and uses modern C# features for optimal performance.
Install CLI tool from NuGet (recommended):
dotnet tool install -g SharpTSOr use TypeScript in a .NET project:
<Project Sdk="SharpTS.Sdk/1.0.0">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<SharpTSEntryPoint>src/main.ts</SharpTSEntryPoint>
</PropertyGroup>
</Project>REPL Mode:
sharptsRun a TypeScript file (interpreted):
sharpts script.tsCompile to .NET assembly:
sharpts --compile script.ts
dotnet script.dllCompile to self-contained executable:
sharpts --compile script.ts -t exe
script.exeAdditional compiler options:
sharpts --compile script.ts --ref-asm # Reference assembly for C# interop
sharpts --compile script.ts --verify # Verify emitted IL
sharpts --compile script.ts --preserveConstEnums # Keep const enumsGenerate NuGet package:
sharpts --compile Library.ts --pack # Creates Library.1.0.0.nupkg
sharpts --compile Library.ts --pack --version 2.0.0-beta # Custom version
sharpts --compile Library.ts --pack --push https://api.nuget.org/v3/index.json --api-key $KEYPackage metadata is read from package.json in the source directory.
Decorator support:
Decorators are enabled by default (TC39 Stage 3).
sharpts script.ts # Stage 3 decorators (default)
sharpts --experimentalDecorators script.ts # Legacy (Stage 2) decorators
sharpts --noDecorators script.ts # Disable decorators// hello.ts
console.log("Hello, World!");$ sharpts hello.ts
Hello, World!// animals.ts
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
speak(): string {
return this.name + " makes a sound";
}
}
class Dog extends Animal {
speak(): string {
return this.name + " barks!";
}
}
let dog = new Dog("Rex");
console.log(dog.speak());$ sharpts animals.ts
Rex barks!// functional.ts
let numbers: number[] = [1, 2, 3, 4, 5];
let doubled = numbers.map((n: number): number => n * 2);
let evens = numbers.filter((n: number): boolean => n % 2 == 0);
let sum = numbers.reduce((acc: number, n: number): number => acc + n, 0);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(evens); // [2, 4]
console.log(sum); // 15# Compile to .NET assembly
$ sharpts --compile functional.ts
# Run the compiled assembly
$ dotnet functional.dll
[2, 4, 6, 8, 10]
[2, 4]
15// Use BCL types directly in TypeScript
@DotNetType("System.Text.StringBuilder")
declare class StringBuilder {
constructor();
append(value: string): StringBuilder;
toString(): string;
}
let sb = new StringBuilder();
sb.append("Hello from .NET!");
console.log(sb.toString());$ sharpts --compile dotnet-example.ts
$ dotnet dotnet-example.dll
Hello from .NET!// Compile your TypeScript with --ref-asm:
var person = new Person("Alice", 30.0); // Direct instantiation
Console.WriteLine(person.name); // Direct property access
string greeting = person.greet(); // Typed return values- Using .NET Types - Use .NET BCL and libraries from TypeScript
- .NET Integration - Consume compiled TypeScript from C#
- MSBuild SDK Guide - Integrate SharpTS into your .NET build process
- Architecture Guide - Deep dive into the compiler/interpreter internals
- Contributing Guide - How to contribute to the project
SharpTS is under active development. See STATUS.md for current feature support and roadmap.
The standard test suite (xUnit, in SharpTS.Tests/) runs via:
dotnet testTwo additional conformance suites live as standalone projects (not in SharpTS.sln, so the standard dotnet test doesn't pick them up). They each pin against an external corpus via git submodule:
- SharpTS.Test262/ — TC39 ECMA-262 conformance, interpreter + compiled-IL modes.
- SharpTS.TypeScriptConformance/ — TypeScript conformance against the canonical
microsoft/TypeScripttest corpus, type-checker only.
Initialize the submodules and invoke the projects explicitly:
git submodule update --init external/test262 external/typescript
dotnet test SharpTS.Test262/SharpTS.Test262.csproj
dotnet test SharpTS.TypeScriptConformance/SharpTS.TypeScriptConformance.csprojBoth suites use a committed-baseline + diff harness — runs hard-fail on regression or new-pass against the committed bucket assignments. Update baselines after intentional changes via SHARPTS_TEST262_UPDATE_BASELINE=1 or SHARPTS_TSCONFORMANCE_UPDATE_BASELINE=1.
Windows note: the
microsoft/TypeScriptrepo contains paths exceeding Windows' default 260-charMAX_PATH. Setgit config --global core.longpaths truebefore initializing theexternal/typescriptsubmodule.
Contributions are welcome! Please read our Contributing Guide for details on:
- Code style guidelines
- How to add new language features
- Submitting pull requests
This project is licensed under the MIT License - see the LICENSE file for details.