# Every type, in one list

> The complete vocabulary of built-in types — the scalars you can store, the collections, the two callable spellings (`Action` and `Func`), and the wrappers a component parameter may take. If a type is not on this page and you did not declare it yourself, it does not exist.

<!-- id: types-vocabulary · area: types · stability: stable · html: https://osysharp.com/reference/types/vocabulary/ -->

## Summary        {#summary}
[Types](https://osysharp.com/reference/types/index/) explains the types with a wrinkle. This page is the other half: the **complete list**, so that
"does the language have a type for this?" is a question you can answer by looking rather than by guessing.

It is worth having because guessing goes wrong in a specific way — you invent a name for something that already
exists. There is no `Command` type for a callable; it is `Action`. There is no `Set<T>`; it is `HashSet<T>`. Every
name below is one the compiler matches, and the list is checked against the compiler itself, so it cannot quietly
fall behind.

Anything not on this page is a type **you** declare — an `entity`, an `enum`, a `class`, or a component's own type
parameter.

## Description    {#description}

### Scalars and value kinds    {#scalars}
The storable types. These are what an entity member, a function local, or a component parameter may be.

| Type | What it is |
|---|---|
| `string` | Text. `default(string)` is null, exactly as in C#. |
| `char` | A single character, in single quotes. See [char](https://osysharp.com/reference/types/char/). |
| `int` | A 32-bit integer. |
| `long` | A 64-bit integer. See [long](https://osysharp.com/reference/types/long/). |
| `double` | A double-precision float — measurements, science. |
| `bool` | True or false. |
| `decimal` | Exact base-10 — money, quantities. See [decimal](https://osysharp.com/reference/types/decimal/). |
| `bigdecimal` | Exact base-10 with 38 significant digits, for when `decimal`'s ~28 are not enough. See [bigdecimal](https://osysharp.com/reference/types/bigdecimal/). |
| `DateTime` | A date and time. See [DateTime](https://osysharp.com/reference/types/datetime/). |
| `DateTimeOffset` | An instant together with its UTC offset. See [DateTimeOffset](https://osysharp.com/reference/types/datetimeoffset/). |
| `DateOnly` | A calendar date with no time of day. |
| `TimeOnly` | A time of day with no date. |
| `TimeSpan` | A duration. See [TimeSpan (durations)](https://osysharp.com/reference/types/timespan/). |
| `Guid` | A globally unique id. |
| `Json` | An arbitrary JSON document. |
| `RichText` | Formatted prose, stored as a rich-text document. |
| `Markdown` | A section-addressable markdown document. See [Markdown](https://osysharp.com/reference/types/markdown/). |
| `Vector` | An embedding, for similarity search; `[MaxLength]` sets the dimensions. |
| `TimeZoneInfo` | A time zone, stored as its IANA id, e.g. `Europe/Stockholm` — C#'s TimeZoneInfo. |
| `Culture` | A BCP-47 culture token, e.g. `sv-SE`. |
| `Geography` | A point, line or polygon on the earth, as GeoJSON. See [Geography](https://osysharp.com/reference/types/geography/). |

A bare member of one of these is **required** unless the type has an honest zero — see
[Optional and required members](https://osysharp.com/reference/types/optional-and-required/), which is the rule that decides whether `?` is needed.

### Which collection types may I write?    {#collections}

| You write | What it is |
|---|---|
| `T[]` | An array. |
| `T?[]` | An array whose ELEMENTS may be null — `string?[]`, `decimal?[]`. (`T[]?` is an array that may itself be null.) |
| `T[][]` | A JAGGED array — a collection of collections, which is how you spell a grid. Indexes as `g[y][x]`, on both sides of an assignment. `T[,]` (rectangular) is not a type here, and the compiler says so and points at this form. |
| `byte[]` | Binary data — the one array form that is a scalar rather than a collection. |
| `List<T>` | An ordered, mutable list. |
| `HashSet<T>` | A set of distinct values. |
| `Dictionary<K, V>` | A keyed map. |
| `stream<T>` | A collection that is still being written. A function returning one produces its results with `yield return`, and a `live var` bound to it renders each item as it arrives — see [yield — a function that produces results over time](https://osysharp.com/reference/function/yield/). |

An entity's **child rows** are not one of these — they are a collection property on the parent, described in
[relations](https://osysharp.com/reference/entity/relations/). Reach for `List<T>` for an in-memory list, never to hold children.

**A jagged array is not a separate kind.** `T[]` *is* a collection of `T`, so `T[][]` is a collection of those.
The outer rank is a `List`, so a grid **can be appended to** (`board.Add(row)`) and a `List<T[]>` goes straight into
one — a bare `T[]` value does not, for the reason every `T[]` → `List<T>` is refused: an array cannot promise the
`.Add` the slot offers. So build the grid as a `List<T[]>` and assign it as it stands, without a `.ToArray()`.

```osy title="a grid — build it, read it, write it" test app=text-search
int[][] Grid(int w) {
  var rows = new List<int[]>();
  for (var y = 0; y < w; y = y + 1) {
    var row = new List<int>();
    for (var x = 0; x < w; x = x + 1) { row.Add(0); }
    rows.Add(row.ToArray());
  }
  int[][] board = rows;                     // the List goes straight in — no `.ToArray()` on the outer rank
  board[0][0] = 1;                          // write a cell
  return board;
}

int[][] Laid() { int[][] board = [[1, 2], [3, 4]]; return board; }   // …or laid out literally
```

### `new T[n]` — n copies of the default    {#new-array}
`new T[n]` is an array of `n` copies of `default(T)`, as in C#. For a number that is `0`, for a `bool` `false`, for a
`char` `'\0'`, for a `DateTime` `DateTime.MinValue`, for a `TimeSpan` `TimeSpan.Zero`, and for an enum its zero
member. For a `string` or a class it is **null**, so `new string[3]` is a `string?[]`. A slot you have not written
reads as null, so read it with `?? ""` or check it for null first. The same rule holds in a function and in the
browser.

```osy title="a buffer you fill in afterwards" test app=text-search
string Labels() {
  var names = new string[3];
  names[0] = "first";
  names[2] = "third";
  return string.Join(",", names.Select(n => n ?? "-"));   // "first,-,third"
}
```

⚠ **`int[,]` does not exist.** A rectangular array is a distinct type in C# and not one Osy# has; the compiler
refuses it by name and tells you to write `int[][]`, which indexes identically.

### How do I type a function value?    {#callables}
Two spellings, both exactly C#'s, and there are no others:

| You write | What it is |
|---|---|
| `Action` | A callback that takes nothing and returns nothing. |
| `Action<T…>` | A callback that takes arguments and returns nothing. |
| `Func<T…, TResult>` | A callback that returns a value. The **last** type argument is the return type. |

```osy title="declaring a callback parameter and a member" syntax
component PrimaryButton(string label, Action onPress) { … }

class MenuEntry {
  public string Label;
  public Action Run;          // the verb to run — an Action, not a "Command"
}
```

`Func` with no type argument is an error: a function that returns something must say what. For a callback that
returns nothing, use `Action`.

**Calling one.** A callable is invoked exactly as in C# — `run()` on a local or parameter, `entry.Run()` on a class
member, and `Run()` unqualified inside the class that declares it:

```osy title="invoking one — on a parameter, and on a member" syntax
class MenuEntry {
  public string Label;
  public Action Run;
}

component Menu(MenuEntry[] entries, Action onDismiss) {
  action Choose(MenuEntry entry) {
    entry.Run();      // run the verb the caller put on this entry
    onDismiss();      // and the callback this component was given
  }
  …
}
```

The argument count and types are checked against the callable's signature, so `Action<int>` invoked with a string is
a compile error rather than a surprise on the client.

**A verb call evaluates to nothing.** It is fire-and-forget: the call does not wait for the verb to finish and yields
no value, so a `Func<…, T>` cannot be invoked — the compiler says so by name rather than handing you a value that
never arrives. Use `Action` for a callback and a plain function when you want a result.

### Component-parameter wrappers    {#component-props}
Writable on a `component` parameter, where they mean something the plain type cannot say:

| You write | What it is |
|---|---|
| `Binding<T>` | A two-way binding — the component **reads and writes** the caller's value. |
| `Query<T>` | A reactive query handle the component re-reads as the data changes. |
| `Content` | An opaque children slot — whatever the caller nests inside. |
| `Slot` | A named children slot. See [Slot (child content)](https://osysharp.com/reference/ui/slots/). |

```osy syntax
component TypeDropdown(Binding<OrganizationType> value) { … }
```

### Reading a value out of text    {#parsing}
`int.Parse`, `long.Parse`, `decimal.Parse`, `double.Parse` and `bool.Parse` read a value of their type out of a `string`, as
C# does. Numbers are read in the current culture, as C#'s are: the viewer's, else `app.DefaultCulture`, else the invariant
culture (`1234.5`) — so under sv-SE `decimal.Parse("1 234,5")` is 1234.5 and `"1234.5"` is an error. Pass
`CultureInfo.InvariantCulture` to read text a machine wrote (`decimal.Parse(s, CultureInfo.InvariantCulture)`). The same
text gives the same number on the server and in the browser ([Culture formatting — ToString(format, culture)](https://osysharp.com/reference/stdlib/culture-formatting/)). `bool.Parse` takes `true` or `false` in any letter case. Text that is not a value of the type
is an **error**, never a quiet `0` or `false`: catch it where a person typed the text, and let it fail where your own code
produced it.

A `double` also holds IEEE 754's non-numbers, spelled as in C#: `double.NaN`, `double.PositiveInfinity`,
`double.NegativeInfinity` (and `double.Epsilon`, the smallest positive value). A NaN is equal to nothing, itself included,
so `x == double.NaN` is always `false` — ask with `double.IsNaN(x)`, `double.IsInfinity(x)`, `double.IsPositiveInfinity(x)`,
`double.IsNegativeInfinity(x)` or `double.IsFinite(x)`. They answer the same on the server, in the browser and in a stored
query, and a query sorts NaN before every number, as C# does.

### Types you declare    {#declared}
Everything else is yours: an `entity` (persisted), an `enum`, a plain `class` (in-memory), and a component's own
type parameters. Those are named by their declaration and scoped by [namespace](https://osysharp.com/reference/types/namespace/) and [type visibility (public / internal)](https://osysharp.com/reference/types/visibility/).

## Examples       {#examples}

Scalars and a collection, together in one function, so the spellings on this page are shown compiling rather than
only described. (Callables belong to a component or a class, so their example lives in **Callables** above.)

```osy title="scalars and a collection" test app=text-search
string Summarise(string title, List<decimal> amounts) {
  decimal total = 0;
  foreach (var a in amounts) {
    if (a > 0) total = total + a;
  }
  return title + ": " + total;
}
// Summarise("Q1", [10, -5, 20])   ->  "Q1: 30"
```

Reading values out of text — the typed amount is caught, because a person typed it; the rest come from systems that promise
the format, so a bad value fails loudly.

```osy title="reading numbers and a yes/no out of text" test app=text-search
decimal? TypedAmount(string typed) {
  decimal? amount = null;
  try { amount = decimal.Parse(typed); } catch { }
  return amount;
}

long IssuedSequence(string issued) { return long.Parse(issued); }
double SensorReading(string text) { return double.Parse(text); }
bool FeatureFlag(string text) { return bool.Parse(text); }
```

## See also       {#see-also}
- [Types](https://osysharp.com/reference/types/index/) — the types with a wrinkle worth reading about first
- [Optional and required members](https://osysharp.com/reference/types/optional-and-required/) — which bare members are required, and when `?` is needed
- [entity members](https://osysharp.com/reference/entity/properties/) — declaring these as entity members
- [component](https://osysharp.com/reference/ui/component/) — where `Binding<T>`, `Query<T>`, `Content` and `Slot` are used
- [Classes](https://osysharp.com/reference/class/index/) — plain in-memory value shapes
