Tsonic GitHub

Import Examples

Module imports and exports in Tsonic.

Local Imports

Local imports must use the .js extension:

// models/User.ts
export interface User {
  id: number;
  name: string;
}

export class UserService {
  getUser(id: number): User {
    return { id, name: "Alice" };
  }
}
// App.ts
import { Console } from "@tsonic/dotnet/System.js";
import { User, UserService } from "./models/User.js";

export function main(): void {
  const service = new UserService();
  const user = service.getUser(1);
  Console.writeLine(user.name);
}

Relative Paths

// Same directory
import { helper } from "./helper.js";

// Parent directory
import { config } from "../config.js";

// Nested path
import { utils } from "./lib/utils/index.js";

Named Exports

// utils.ts
export const PI = 3.14159;

export function add(a: number, b: number): number {
  return a + b;
}

export function multiply(a: number, b: number): number {
  return a * b;
}

export interface Point {
  x: number;
  y: number;
}
// App.ts
import { Console } from "@tsonic/dotnet/System.js";
import { PI, add, Point } from "./utils.js";

const point: Point = { x: 10, y: 20 };
Console.writeLine(add(1, 2));
Console.writeLine(PI);

Namespace Import

Import all exports under a namespace:

// utils.ts
export const PI = 3.14159;
export function add(a: number, b: number): number {
  return a + b;
}
// App.ts
import { Console } from "@tsonic/dotnet/System.js";
import * as utils from "./utils.js";

Console.writeLine(utils.PI);
Console.writeLine(utils.add(1, 2));

Re-exports (Barrel Files)

Create index files to re-export from multiple modules:

// models/User.ts
export interface User {
  id: number;
  name: string;
}

// models/Product.ts
export interface Product {
  id: number;
  price: number;
}

// models/index.ts
export { User } from "./User.js";
export { Product } from "./Product.js";
// App.ts
import { User, Product } from "./models/index.js";

Type-Only Imports

Import types without runtime code:

// types.ts
export interface Config {
  host: string;
  port: number;
}
// App.ts
import type { Config } from "./types.js";

function loadConfig(): Config {
  return { host: "localhost", port: 8080 };
}

.NET Imports

.NET imports use the .js extension (and do not use .ts):

// System namespace
import { Console } from "@tsonic/dotnet/System.js";

// System.IO namespace
import { File, Directory } from "@tsonic/dotnet/System.IO.js";

// System.Collections.Generic
import { List, Dictionary } from "@tsonic/dotnet/System.Collections.Generic.js";
export function main(): void {
  Console.writeLine("Hello from .NET!");

  const exists = File.exists("config.json");
  const files = Directory.getFiles(".");
}

Directory Structure and Namespaces

File paths map to C# namespaces:

src/
├── App.ts           → MyApp.App
├── models/
│   ├── User.ts      → MyApp.Models.User
│   └── Product.ts   → MyApp.Models.Product
└── services/
    └── api.ts       → MyApp.Services.Api

When importing across directories:

// src/services/api.ts
  import { User } from "../models/User.js";
// Resolves to namespace MyApp.Models

export function getUser(): User {
  return { id: 1, name: "Alice" };
}

Multiple File Project

// src/models/User.ts
export interface User {
  id: number;
  name: string;
}

// src/services/UserService.ts
import { User } from "../models/User.js";

export class UserService {
  private users: User[] = [];

  add(user: User): void {
    this.users.push(user);
  }

  find(id: number): User | null {
    for (const user of this.users) {
      if (user.id === id) {
        return user;
      }
    }
    return null;
  }
}

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

export function main(): void {
  const service = new UserService();

  service.add({ id: 1, name: "Alice" });
  service.add({ id: 2, name: "Bob" });

  const user = service.find(1);
  if (user) {
    Console.writeLine(user.name);
  }
}

Build with:

tsonic build src/App.ts --namespace MyApp