.NET Integration Examples
Using .NET Base Class Library (BCL) in Tsonic.
File Operations
import { Console } from "@tsonic/dotnet/System.js";
import { File, Directory, Path } from "@tsonic/dotnet/System.IO.js";
export function main(): void {
// Read file
const content = File.readAllText("input.txt");
Console.writeLine(content);
// Write file
File.writeAllText("output.txt", "Hello, World!");
// Check existence
if (File.exists("config.json")) {
const config = File.readAllText("config.json");
}
// List files
const files = Directory.getFiles(".");
for (const file of files) {
Console.writeLine(file);
}
// Create directory
Directory.createDirectory("data");
// Path manipulation
const fullPath = Path.combine("data", "file.txt");
const extension = Path.getExtension("file.txt");
const filename = Path.getFileName("/path/to/file.txt");
}
Collections
import { Console } from "@tsonic/dotnet/System.js";
import {
List,
Dictionary,
HashSet,
} from "@tsonic/dotnet/System.Collections.Generic.js";
export function main(): void {
// List<T>
const numbers = new List<number>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
Console.writeLine(numbers.count);
Console.writeLine(numbers.contains(2));
numbers.remove(2);
numbers.clear();
// Dictionary<K,V>
const ages = new Dictionary<string, number>();
ages.add("Alice", 30);
ages.add("Bob", 25);
const aliceAge = ages["Alice"];
const hasAlice = ages.containsKey("Alice");
// HashSet<T>
const unique = new HashSet<string>();
unique.add("a");
unique.add("b");
unique.add("a"); // Duplicate, ignored
Console.writeLine(unique.count); // 2
// Dictionary with number keys
const byId = new Dictionary<number, string>();
byId.add(1, "Alice");
byId.add(2, "Bob");
const name = byId[1]; // "Alice"
}
Tuples
import { Console } from "@tsonic/dotnet/System.js";
export function main(): void {
// Create tuple
const point: [number, number] = [10, 20];
// Destructure
const [x, y] = point;
Console.writeLine(`Point: ${x}, ${y}`);
// Return multiple values
const result = getMinMax([5, 2, 8, 1, 9]);
Console.writeLine(`Min: ${result[0]}, Max: ${result[1]}`);
}
function getMinMax(numbers: number[]): [number, number] {
let min = numbers[0];
let max = numbers[0];
for (const n of numbers) {
if (n < min) min = n;
if (n > max) max = n;
}
return [min, max];
}
LINQ Operations
import { Enumerable } from "@tsonic/dotnet/System.Linq.js";
interface User {
id: number;
name: string;
age: number;
}
export function main(): void {
const users: User[] = [
{ id: 1, name: "Alice", age: 30 },
{ id: 2, name: "Bob", age: 25 },
{ id: 3, name: "Charlie", age: 35 },
];
// Types are contextually inferred from the array element type
// Filter (Where)
const adults = Enumerable.where(users, (u) => u.age >= 30);
// Transform (Select)
const names = Enumerable.select(users, (u) => u.name);
// First matching
const alice = Enumerable.firstOrDefault(users, (u) => u.name === "Alice");
// Sorting
const byAge = Enumerable.orderBy(users, (u) => u.age);
// Aggregation
const totalAge = Enumerable.sum(users, (u) => u.age);
const averageAge = Enumerable.average(users, (u) => u.age);
// Any/All
const anyAdult = Enumerable.any(users, (u) => u.age >= 18);
const allAdults = Enumerable.all(users, (u) => u.age >= 18);
}
Lambda parameter types are contextually inferred from the collection element type.
String Operations
import { Console, String } from "@tsonic/dotnet/System.js";
import { StringBuilder } from "@tsonic/dotnet/System.Text.js";
export function main(): void {
// Efficient string building
const sb = new StringBuilder();
sb.append("Hello");
sb.append(", ");
sb.append("World");
sb.appendLine("!");
const result = sb.toString();
Console.writeLine(result);
// String formatting
const formatted = String.format("Name: {0}, Age: {1}", "Alice", 30);
}
Date and Time
import { Console, DateTime, TimeSpan } from "@tsonic/dotnet/System.js";
export function main(): void {
// Current time
const now = DateTime.now;
const utcNow = DateTime.utcNow;
// Create specific date
const date = new DateTime(2024, 12, 25);
// Date arithmetic
const tomorrow = now.addDays(1);
const nextWeek = now.addDays(7);
const nextMonth = now.addMonths(1);
// TimeSpan
const duration = new TimeSpan(1, 30, 0); // 1 hour 30 minutes
const later = now.Add(duration);
// Formatting
const formatted = now.toString("yyyy-MM-dd HH:mm:ss");
Console.writeLine(formatted);
// Parsing
const parsed = DateTime.parse("2024-12-25");
}
Console I/O
import { Console, ConsoleColor } from "@tsonic/dotnet/System.js";
export function main(): void {
// Output
Console.writeLine("Hello, World!");
Console.write("No newline");
// Formatted output
Console.writeLine("Name: {0}, Age: {1}", "Alice", 30);
// Colors
Console.foregroundColor = ConsoleColor.green;
Console.writeLine("Green text");
Console.resetColor();
// Read input
Console.write("Enter name: ");
const name = Console.readLine();
Console.writeLine(`Hello, ${name}!`);
}
Math Operations
import { Math, Random } from "@tsonic/dotnet/System.js";
export function main(): void {
// Basic operations
const abs = Math.abs(-5); // 5
const max = Math.max(10, 20); // 20
const min = Math.min(10, 20); // 10
// Rounding
const floor = Math.floor(4.7); // 4
const ceil = Math.ceiling(4.2); // 5
const round = Math.round(4.5); // 4 (banker's rounding)
// Power and roots
const pow = Math.pow(2, 10); // 1024
const sqrt = Math.sqrt(16); // 4
// Trigonometry
const sin = Math.sin(Math.pi / 2);
const cos = Math.cos(0);
// Random
const random = new Random();
const value = random.next(1, 100); // 1-99
const doubleValue = random.nextDouble(); // 0.0-1.0
}
Environment
import { Console, Environment } from "@tsonic/dotnet/System.js";
export function main(): void {
// Environment variables
const path = Environment.getEnvironmentVariable("PATH");
Environment.setEnvironmentVariable("MY_VAR", "value");
// System info
const machineName = Environment.machineName;
const userName = Environment.userName;
const osVersion = Environment.osVersion;
// Current directory
const cwd = Environment.currentDirectory;
// Command line args
const args = Environment.getCommandLineArgs();
for (const arg of args) {
Console.writeLine(arg);
}
// Exit code
Environment.exit(0);
}
HTTP Client
import { Console } from "@tsonic/dotnet/System.js";
import { HttpClient } from "@tsonic/dotnet/System.Net.Http.js";
export async function main(): Promise<void> {
const client = new HttpClient();
// GET request
const response = await client.getStringAsync("https://api.example.com/data");
Console.writeLine(response);
}
JSON Serialization
import { Console } from "@tsonic/dotnet/System.js";
import { JsonSerializer } from "@tsonic/dotnet/System.Text.Json.js";
interface User {
id: number;
name: string;
}
export function main(): void {
// Serialize
const user: User = { id: 1, name: "Alice" };
const json = JsonSerializer.serialize(user);
Console.writeLine(json); // {"id":1,"name":"Alice"}
// Deserialize
const parsed = JsonSerializer.deserialize<User>('{"id":2,"name":"Bob"}');
Console.writeLine(parsed?.name); // Bob
}
NativeAOT Compatibility
Tsonic automatically generates a JsonSerializerContext for NativeAOT compatibility.
You don't need to do anything special—just use JsonSerializer as shown above.
Behind the scenes, Tsonic:
- Detects all
JsonSerializer.Serialize()andDeserialize<T>()calls - Collects the types being serialized
- Generates
__tsonic_json.g.cswith[JsonSerializable]attributes - Rewrites calls to use the generated context
This ensures your code works in NativeAOT without reflection-based serialization.