Edit source

Source semantics

Ordinary TypeScript remains ordinary TypeScript:

export interface User {
  readonly id: string;
  name: string;
}

export function rename(user: User, name: string): User {
  return { ...user, name };
}

Inheritance and overrides

Write normal TypeScript inheritance:

class Message {
  text = "base";

  render(): string {
    return this.text;
  }
}

class EmphaticMessage extends Message {
  text = "important";

  render(): string {
    return `${super.render()}!`;
  }
}

export function show(message: Message): string {
  return message.render();
}

The checked source program records that the derived members override base members and that message.render() is virtual dispatch. C# emits the required virtual and override members. Rust emits its equivalent closed dispatch model. Source code does not add a C#- or Rust-specific override marker.

Target-native inheritance is also evidence-driven. Extending a provider type is accepted only when that provider exposes an exact legal base contract.

Tsonic source modules add types and operations only where JavaScript and TypeScript do not express a required native distinction.

Type transformations

Standard utility types are checked as TypeScript and then erase:

interface User {
  id: string;
  name: string;
  active?: boolean;
}

type Patch = Partial<User>;
type NameOnly = Pick<User, "name">;

The target receives the resolved shape, not a request to implement a native type named Partial or Pick. The complete pinned inventory and the distinct any and unknown target contracts are in TypeScript types and utilities.

Exact primitives

import type { int32, uint8, float64 } from "@tsonic/core/types.js";

export function average(total: int32, count: uint8): float64 {
  return total / count;
}

These aliases may all erase to TypeScript number while checking, but TSTS retains their exact source-semantic identities for the target.

Reference arguments

import { readWriteRef, writeOnlyRef } from "@tsonic/core/lang.js";

declare function divide(
  numerator: number,
  denominator: number,
  quotient: number,
  remainder: number,
): void;

let quotient = 0;
let remainder = 0;
divide(17, 5, writeOnlyRef(quotient), writeOnlyRef(remainder));

The selected provider signature determines whether a marker is legal. A marker does not turn an arbitrary value into a writable native location.

Typed locations

import {
  addressOf,
  equalPointer,
  loadPointer,
  storePointer,
} from "@tsonic/core/lang.js";
import type { int32, Pointer } from "@tsonic/core/types.js";

function increment(pointer: Pointer<int32>): void {
  storePointer(pointer, loadPointer(pointer) + 1);
}

let value: int32 = 1;
const pointer = addressOf(value);
increment(pointer);
const sameLocation = equalPointer(pointer, addressOf(value));

Pointer<T> is a typed mutable storage location. It is not a raw address. C# lowers it to its closed Location<T> carrier; Rust lowers it to its own closed location representation. Identity follows storage, not wrapper-object identity.

Native pointers and safety

Native pointer operations require exact target support and an explicit safety contract:

import {
  loadNativePointer,
  offsetNativePointer,
  unsafeContext,
} from "@tsonic/core/lang.js";
import type {
  NativePointer,
  int32,
  nativeInt,
} from "@tsonic/core/types.js";

export function read(
  pointer: NativePointer<int32>,
  offset: nativeInt,
): int32 {
  return unsafeContext(loadNativePointer(offsetNativePointer(pointer, offset)));
}

The safety region and any declaration-level requires-unsafe contract are independent controls. Tsonic does not infer one from the other.

Target-native spelling

Target modules may provide native aliases. For example, C# offers int, out, and ptr; Rust offers explicit lifetime and reference types. Neutral library code should prefer @tsonic/core unless it intentionally exposes a target-native contract.

The exhaustive catalog is in neutral types and markers.