Working with Data

This page covers how C# data types are represented in the JavaScript Transpose emits — which matters both for performance and for what crosses the interop boundary cleanly.

Primitive types

C# type JavaScript representation Notes
string string UTF-16, same as .NET
bool boolean
byte, sbyte number Integer arithmetic, truncated to range
short, ushort number
int, uint number
float, double number IEEE 754, exactly as .NET
char number A UTF-16 code unit
long, ulong System.Int64 object 64-bit exact; not a JS number
decimal System.Decimal object Exact decimal arithmetic; not a JS number
IntPtr, UIntPtr No browser equivalent

Integers

A JavaScript number is a 64-bit float, so it represents every 32-bit integer exactly. Transpose emits the truncation and wrap-around that C# integer arithmetic requires, so int overflow behaves the way it does on .NET rather than silently turning into a float.

long and decimal are objects

This is the mapping most worth knowing. long and decimal cannot be held exactly in a JavaScript number, so the runtime implements them as real types (System.Int64 and System.Decimal) with their full .NET arithmetic. Two consequences:

  • No precision loss. long is exact to 64 bits; decimal does exact decimal arithmetic. Money and identifiers survive round trips.
  • They are objects at the interop boundary. A long handed to a JavaScript library is not a number, and JSON.stringify will not serialize it as one. Convert at the boundary — (double)value when the range is safe, value.ToString() when it is not — or keep such fields as string in the DTOs you exchange with JavaScript.

Arithmetic on long and decimal also allocates and goes through method calls rather than compiling to a machine operation. Prefer int/double in a hot loop.

Arrays

C# arrays map to JavaScript arrays.

int[] numbers = new int[] { 1, 2, 3 };
var numbers = [1, 2, 3];

Indexing and Length work as expected. A JavaScript array is growable while a C# array is fixed-size — Transpose does not add a runtime guard for that, so code that reaches into the array from JavaScript and pushes onto it will produce an array longer than its C# Length implies.

Multidimensional arrays (int[,]) are represented with the runtime's own array type rather than a nested JavaScript array, so they do not cross the interop boundary as plainly as a single-dimensional array does.

Span<T> and ReadOnlySpan<T> are represented as the underlying array. Note that the implicit array-to-Span<T> conversion is not modelled — Span<int> s = new int[3]; does not produce a working span. Use the array directly.

Collections

The runtime implements the standard generic collections — List<T>, Dictionary<TKey, TValue>, HashSet<T>, Queue<T>, Stack<T>, SortedDictionary<TKey, TValue>, LinkedList<T> — with .NET semantics, including correct key equality (Equals/GetHashCode) for dictionary and set keys.

var list = new List<string> { "a", "b" };
list.Add("c");

var dict = new Dictionary<string, int>();
dict["key"] = 123;

These are runtime objects, not plain JavaScript values: a List<T> is not a JavaScript array and a Dictionary<K,V> is not a plain object. To hand a collection to JavaScript, project it first — list.ToArray() for an array, or build an [ObjectLiteral] type for a map-shaped payload. See JSON Serialization.

DateTime and TimeSpan

System.DateTime is backed by JavaScript's Date and exposes the .NET API on top of it — components, arithmetic, Kind, parsing and format strings. System.TimeSpan is its own runtime type.

Because the underlying Date has millisecond resolution, DateTime.Ticks is exact only to the millisecond; sub-millisecond precision is not preserved. The browser's time zone is what DateTime.Now and local-time conversions use, and there is no time-zone database, so TimeZoneInfo lookups for arbitrary zones are not available. Work in UTC and format for display.

Guid

System.Guid is implemented, including NewGuid(), parsing, and the standard format strings. It is a runtime object, so serialize it as a string when crossing into JavaScript.

Strings, text and regular expressions

string is a JavaScript string, so it is cheap to pass across the boundary. The runtime implements the .NET string API on top of it — including composite formatting (string.Format, interpolated strings) and the numeric/date format specifiers.

System.Text.RegularExpressions is implemented over the JavaScript regular expression engine. Most patterns behave the same, but .NET-only constructs (balancing groups, some lookbehind forms, and RegexOptions that have no JavaScript flag) are not available.

© 2026 Curiosity. All rights reserved.