# Types & values

> Langoost's value types — int, float, bool, string, array, object, void/nil, any, and the json/yaml/xml data types — plus number literals, template strings, and conversion.

# Types & values

Langoost has a small set of value types. Type annotations are **optional**, and
values are strongly typed at runtime. A lightweight static checker also runs at
compile time — see [Static type checking](#static-type-checking) below.

## Value types

| Type | Description | Example |
| --- | --- | --- |
| `int` | 64-bit signed integer | `42`, `-7`, `0` |
| `float` | 64-bit IEEE-754 double | `3.14`, `-0.5`, `1e10` |
| `bool` | Boolean | `true`, `false` |
| `string` | UTF-8 text | `"hello"`, `'world'` |
| `array` | Ordered list of any values | `[1, "two", true]` |
| `object` | Key/value structure | `{x: 10, y: 20}` |
| `void` | Absence of a value (`nil`) | `nil` |
| `any` | Accepts any type, unchecked | — |
| `json` / `yaml` / `xml` | String annotated as that data format | `{key: "val"}` |

Array types use a `[]` suffix on the element type: `int[]`, `string[]`.

## Number literals

Integers can be written in several bases, with `_` as a digit separator; floats
support scientific notation:

```goost
let dec = 1_000_000
let hex = 0xDEAD_BEEF
let bin = 0b1010
let oct = 0o755
let f   = 1.5e-3
```

## Strings

Single and double quotes are both accepted, with escapes `\n`, `\t`, `\r`,
`\"`, `\'`, `\\`, `\0`:

```goost
let a = "hello"
let b = 'world'
```

### Template strings

Backtick strings interpolate embedded expressions with `${...}`:

```goost
let name = "Ada"
println(`Hello, ${name} — you have ${3 + 4} messages`)
```

## Objects

Object literals map keys to values. Keys can be read with dot or bracket access;
brackets also allow dynamic keys:

```goost
let user = {name: "alice", age: 30}
println(user.name)        // "alice"
println(user["age"])      // 30
user["role"] = "admin"    // add / update a field
```

Objects double as maps. To attach a named type, see **[classes & types](/docs/classes)**.

## nil and negative indexing

`nil` is the empty/void value. Arrays and strings support Python-style negative
indices:

```goost
let xs = [10, 20, 30]
println(xs[-1])           // 30  (last element)
let missing = nil
```

## Conversion

Coercion is explicit:

```goost
let n: int = toInt("42")
let f: float = toFloat(n)
let s: string = toString(n)
println(typeof(n))        // "int"
```

The `json`, `yaml`, and `xml` types are strings with special meaning — see the
**[stdlib `json` module](/docs/stdlib/json)** and the `: json` inline-literal
syntax.

## Static type checking

A lightweight, annotation-driven checker runs at compile time. It's intentionally
conservative — it catches obvious mistakes without getting in the way of dynamic
code. It currently verifies that literals match their declared type in four
places:

```goost
let n: int = "oops"          // compile error: expected int
fn area(w: float): float {
    return "nope"            // compile error: expected float
}
```

- `let x: T = literal`
- `x = literal` when `x` is a typed local or global
- `return literal` from a function with a declared return type
- typed parameter defaults

Enforcement covers only the primitive set `int`, `float`, `string`, `bool`, and
`array`. Other annotations — `json`, `any`, class names, interfaces — pass
through unchecked, so dynamic code keeps working. There is no type inference
across expressions yet.