展示 HN:Tsonic 编程语言
Show HN: The Tsonic Programming Language

原始链接: https://tsonic.org

## Tsonic:TypeScript 到原生 .NET 编译器 Tsonic 是一个编译器,它使用 NativeAOT 将 TypeScript/JavaScript 代码转换为快速的原生 .NET 可执行文件。它允许熟悉 TypeScript 的开发者构建高性能应用程序,利用 .NET 标准库和运行时。 **主要特性包括:**原生二进制文件(无需 JavaScript 运行时)、直接访问 .NET BCL、通过 NativeAOT 实现单文件可执行文件,以及完整的 .NET 互操作性。TypeScript 的特性,如类、async/await 和泛型,可以自然地映射到其 .NET 对应项。 Tsonic 利用 **tsbindgen** 从 .dll 或 NuGet 包生成必要的 CLR 绑定,确保准确的类型解析。它通过 npm 安装 (`npm install -g tsonic`),项目通过 `tsonic project init` 初始化。 除了核心功能外,Tsonic 还提供可选的兼容性包,如 `@tsonic/nodejs` 用于 Node 风格的 API,以及 `@tsonic/aspnetcore` 用于构建精简的 ASP.NET Core API。配置通过 `tsonic.json` 文件管理,该工具支持 npm 工作区用于大型项目。该项目采用 MIT 许可。

Hacker News 新闻 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 展示 HN: Tsonic 编程语言 (tsonic.org) 13 分,作者 jeswin,2 小时前 | 隐藏 | 过去 | 收藏 | 2 条评论 示例见此:https://github.com/tsoniclang/proof-is-in-the-pudding Hugo 克隆版(编译为本机代码)见此:https://github.com/tsoniclang/tsumo 目前支持 Linux 和 macOS。 zahlman 33 分钟前 | 下一个 [–] > Tsonic 是一个 TypeScript 到 C# 的编译器 所以,不是一种独立的语言。回复 throwawaygod 25 分钟前 | 上一个 [–] 另一个类似的 TypeScript 编译器:SharpTS [https://news.ycombinator.com/item?id=46557698] 回复 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系方式 搜索:
相关文章

原文

Tsonic is a TypeScript to C# compiler that produces native executables via .NET NativeAOT. Write TypeScript, get fast native binaries.

Why Tsonic?

Tsonic lets TypeScript/JavaScript developers build fast native apps on .NET:

  • Native binaries (no JS runtime).
  • .NET standard library: use the .NET runtime + BCL (files, networking, crypto, concurrency, etc.).
  • Node-style APIs when you want them: optional compatibility packages like @tsonic/nodejs.
  • Still TypeScript: your code still typechecks with tsc. Tsonic also adds CLR-style numeric types like int, uint, long, etc. via @tsonic/core/types.js.
  • Better security: you build on a widely used runtime and standard library with regular updates.

Tsonic targets the .NET BCL (not Node’s built-in modules). If you want Node-like APIs, install @tsonic/nodejs.

Why C# + NativeAOT?

Tsonic compiles TypeScript to C#, then uses the standard CLR NativeAOT pipeline (dotnet publish) to produce native binaries.

TypeScript maps well to C#/.NET:

  • Classes, interfaces, generics: translate naturally to CLR types.
  • Async/await: TS async maps cleanly to Task/ValueTask.
  • Iterators and generators: map to C# iterator patterns.
  • Delegates/callbacks: map to Action/Func without inventing a new runtime ABI.

NativeAOT produces single-file, self-contained native executables.

Details live in the docs: /tsonic/build-output/ and /tsonic/architecture/pipeline/.

Key Features

  • TypeScript to Native: Compile TypeScript directly to native executables
  • Direct .NET Access: Full access to .NET BCL with native performance
  • NativeAOT Compilation: Single-file, self-contained executables
  • Full .NET Interop: Import and use any .NET library
  • ESM Module System: Standard ES modules with .js import specifiers

Installation

npm install -g tsonic

Prerequisites:

Quick Start

Initialize a New Project

mkdir my-app && cd my-app
tsonic project init

This creates:

  • src/App.ts - Entry point
  • tsonic.json - Configuration
  • package.json - With build scripts

Build and Run

npm run build    # Build native executable
./out/app        # Run it

# Or build and run in one step
npm run dev

Example Program

// src/App.ts
import { Console } from "@tsonic/dotnet/System.js";

export function main(): void {
  const message = "Hello from Tsonic!";
  Console.writeLine(message);

  const numbers = [1, 2, 3, 4, 5];
  Console.writeLine(`Numbers: ${numbers.length}`);
}

Using .NET APIs (BCL)

import { Console } from "@tsonic/dotnet/System.js";
import { File } from "@tsonic/dotnet/System.IO.js";
import { List } from "@tsonic/dotnet/System.Collections.Generic.js";

export function main(): void {
  // File I/O
  const content = File.readAllText("./README.md");
  Console.writeLine(content);

  // .NET collections
  const list = new List<number>();
  list.add(1);
  list.add(2);
  list.add(3);
  Console.writeLine(`Count: ${list.count}`);
}

Examples

LINQ extension methods (where, select)

import { List } from "@tsonic/dotnet/System.Collections.Generic.js";
import type { ExtensionMethods as Linq } from "@tsonic/dotnet/System.Linq.js";

type LinqList<T> = Linq<List<T>>;

const xs = new List<number>() as unknown as LinqList<number>;
xs.add(1);
xs.add(2);
xs.add(3);

const doubled = xs.where((x) => x % 2 === 0).select((x) => x * 2).toList();
void doubled;

JSON with the .NET BCL (System.Text.Json)

import { Console } from "@tsonic/dotnet/System.js";
import { JsonSerializer } from "@tsonic/dotnet/System.Text.Json.js";

type User = { id: number; name: string };

const user: User = { id: 1, name: "Alice" };
const json = JsonSerializer.serialize(user);
Console.writeLine(json);

const parsed = JsonSerializer.deserialize<User>(json);
if (parsed !== undefined) {
  Console.writeLine(parsed.name);
}

Minimal ASP.NET Core API

First, add the shared framework + bindings:

tsonic add framework Microsoft.AspNetCore.App @tsonic/aspnetcore

Then write:

import { WebApplication } from "@tsonic/aspnetcore/Microsoft.AspNetCore.Builder.js";

export function main(): void {
  const builder = WebApplication.createBuilder([]);
  const app = builder.build();

  app.mapGet("/", () => "Hello from Tsonic + ASP.NET Core!");
  app.run();
}

tsbindgen (CLR Bindings Generator)

Tsonic doesn’t “guess” CLR types from strings. It relies on bindings packages generated by tsbindgen:

  • Given a .dll (or a directory of assemblies), tsbindgen produces:
    • ESM namespace facades (*.js) + TypeScript types (*.d.ts)
    • bindings.json (namespace → CLR mapping)
    • internal/metadata.json (CLR metadata for resolution)
  • Tsonic uses these artifacts to resolve imports like:
    • import { Console } from "@tsonic/dotnet/System.js"

Tsonic can run tsbindgen for you:

# Add a local DLL (auto-generates bindings if you omit the types package)
tsonic add package ./path/to/MyLib.dll

# Add a NuGet package (auto-generates bindings for the full transitive closure)
tsonic add nuget Newtonsoft.Json 13.0.3

# Or use published bindings packages (no auto-generation)
tsonic add nuget Microsoft.EntityFrameworkCore 10.0.1 @tsonic/efcore

CLI Commands

Command Description
tsonic project init Initialize new project
tsonic generate [entry] Generate C# code only
tsonic build [entry] Build native executable
tsonic run [entry] Build and run
tsonic add package <dll> [types] Add a local DLL + bindings
tsonic add nuget <id> <ver> [types] Add a NuGet package + bindings
tsonic add framework <ref> [types] Add a FrameworkReference + bindings
tsonic restore Restore deps + bindings
tsonic pack Create a NuGet package

Common Options

Option Description
-c, --config <file> Config file (default: tsonic.json)
-o, --out <name> Output name (binary/assembly)
-r, --rid <rid> Runtime identifier (e.g., linux-x64)
-O, --optimize <level> Optimization: size or speed
-k, --keep-temp Keep build artifacts
-V, --verbose Verbose output
-q, --quiet Suppress output

Configuration (tsonic.json)

{
  "$schema": "https://tsonic.dev/schema/v1.json",
  "rootNamespace": "MyApp",
  "entryPoint": "src/App.ts"
}

Project Structure

my-app/
├── src/
│   └── App.ts           # Entry point (exports main())
├── tsonic.json          # Configuration
├── package.json         # NPM package
├── generated/           # Generated C# (gitignored)
└── out/                 # Output executable (gitignored)

Naming Modes

Tsonic supports two binding/name styles:

  • Default: JavaScript-style member names (Console.writeLine)
  • --pure: CLR-style member names (Console.WriteLine)
tsonic project init --pure

Npm Workspaces (Multi-Assembly Repos)

Tsonic projects are plain npm packages, so you can use npm workspaces to build multi-assembly repos (e.g. @acme/domain + @acme/api).

  • Each workspace package has its own tsonic.json and produces its own output (dist/ for libraries, out/ for executables).
  • Build workspace dependencies first (via npm run -w <pkg> ...) before building dependents.
  • For library packages, you can generate tsbindgen CLR bindings under dist/ and expose them via npm exports; Tsonic resolves imports using Node resolution (including exports) and locates the nearest bindings.json.

See /tsonic/dotnet-interop/ for the recommended dist/ + exports layout.

Documentation

Type Packages

Package Description
@tsonic/globals Base types (Array, String, iterators, Promise)
@tsonic/core Core types (int, float, etc.)
@tsonic/dotnet .NET BCL type declarations

License

MIT

联系我们 contact @ memedata.com