Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Types

Types

The values your app computes with, and the declarations that name and scope them. Most scalar types are exactly C#'s — int, long, double, string, bool, Guid work as you expect. The pages here cover the ones with a wrinkle worth knowing up front (decimal, long, and the date/time family) and the file-level declarations: namespace, visibility, and use.

stabletypesguide

Summary#

Osy# is C#, so the types are C#'s types. int, long, double, string, bool, and Guid behave exactly as you expect and need no page of their own. What this area documents is the handful of types with a wrinkle worth knowing before you reach for them — decimal and the date/time family — and the three declarations that name and scope the types you write: namespace, visibility, and use.

Looking for the full list? Every type, in one list enumerates every built-in type in one place — the scalars, the collections, the two callable spellings, and the component-parameter wrappers. Read it when the question is "is there a type for this?" rather than "how does this one behave?".

The one rule that runs through all of it: a value computes to the same answer on the server and in the browser, character for character. A decimal total, a DateTime's parts, a TimeSpan's hours — none of them changes with where the code happens to run.

Description#

The numbers#

Four numeric types, straight from C#: int and long (whole numbers), double (fast, approximate — measurements and science), and decimal (exact base-10 — money, and anything where a fraction of a cent matters). Two earn a page: decimal, because "exact vs approximate" is the choice that quietly decides whether a total is ever a penny off, and long, because whole-number division truncates and because a 64-bit id is exact to its full range on both sides. Reach for decimal when the number is money, long when it is an id or a sequence, double when it is a measurement.

The date and time family#

This is the part to read up front, because the names carry meaning:

  • DateTime — a date and time. It is a wall-clock value, not an instant on a timeline, so nobody's timezone ever shifts it.
  • DateOnly and TimeOnlyDateOnly (a calendar date, no time) and TimeOnly (a time of day, no date).
  • TimeSpan (durations)TimeSpan, a duration: subtract two DateTimes and you get one; add it back and you get a DateTime. Read whole components (.Days, .Hours) or fractional totals (.TotalHours).

TimeSpan, DateOnly, TimeOnly ties the three together — how they combine, and why all of them are exact and side-independent.

The declarations that scope your types#

Three keywords decide where a type lives and who may name it:

  • namespacenamespace X; at the top of a file puts that file's types in X. Optional; omit it and they land in the global namespace.
  • type visibility (public / internal) — a top-level type is public or internal, deciding whether code outside its namespace can name it. The defaults are C#'s: an entity or enum is public, a plain class is internal.
  • useuse Osyrin.X; inside the app { } manifest declares a capability your app depends on, which provisions its tables and types. It is the dependency; a using is just the import that brings the names into scope.

What if my name is already the platform's?#

The Osyrin core namespace is in scope in every app with no using, and it exports 82 type names — many of them ordinary English words (Slot, Group, Match, Point, Month, Now, Uri, Connection, Position). Naming your own type after one is legal, and yours wins; the compiler warns once at the declaration and the platform's type stays reachable by its full name. When your name is already the platform's has the rule, the full list of taken names, and the eleven built-in names that are the exception.

Values the compiler has to know#

Looking for how to DECLARE a named constant? It is const, and it goes wherever you need it:

const int EatSoonDays = 90;                       // top level — shared by every function and page in the app
component Home() { const int Rows = 20; … }       // one component
int F() { const int Limit = 5; … }                // one body
class Rules { public const int Retries = 3; }     // on a class, as in C#

A const folds to its value at every use, so it goes anywhere a literal goes — including inside a query predicate, where a function call cannot (a predicate becomes SQL, and SQL cannot call back into your code). That is the difference between const int Days = 90; and a int Days() { return 90; } helper.

For a value that differs between environments — a base URL, a from-address — you want per-environment config (app.Config) instead, not a constant.

This section is about something else: a few places take a value that must be settled while the app is compiled rather than while it runs — an attribute argument, a config setting, an enum member's label, a workflow message. Constant expressions covers what counts as constant there, including the fact that a long sentence may be split across lines with +.

See also#

Related

Every type, in one list

The complete vocabulary of built-in types — the scalars you can store, the collections, the two callable spellings…

When your name is already the platform's

The platform puts 82 ordinary English words in scope in every app with no `using` — `Slot`, `Group`, `Match`, `Point`…

string literals — ordinary, verbatim and raw

Three ways to write a string, all of them C#'s. The ordinary form processes escapes. The verbatim form (`@"…"`)…

char

A single character, written in single quotes. It is what you get from `s[0]` and from iterating a string, and it is the…

decimal

Exact base-10 arithmetic, for money and anything else where a fraction of a cent matters. It behaves identically…

long

A 64-bit whole number, exact to its full range — ids, sequence numbers, row versions, byte offsets. It holds the same…

DateTime

A date and time. It is a wall-clock value, not an instant on a timeline, so it is never shifted by anybody's timezone…

TimeSpan (durations)

`TimeSpan` is the duration type — a length of time, as in C#. Build one with the `TimeSpan.FromX` factories or `new…

DateOnly and TimeOnly

`DateOnly` is a calendar date (no time); `TimeOnly` is a time of day (no date) — the C# types. Build them with `new…

TimeSpan, DateOnly, TimeOnly

A duration, a bare date, and a bare time of day. Subtracting two DateTimes gives a TimeSpan; adding one back gives a…

namespace

Declares the namespace a file's types belong to, written once at the top of the file. It is optional — a file without…

type visibility (public / internal)

A top-level type carries a public or internal visibility that decides whether code outside its namespace can name it…

use

Declares a capability your app depends on, written inside the `app { }` manifest block. It provisions the capability…

Classes

A class is an in-memory shape — data plus the behaviour that belongs to it — and it never touches the database. That is…

entity

Declares a persisted type — a table of rows the app stores, queries and secures. Every entity gets an Id and audit…