Skip to content

ThinkLang Type Reference

ThinkLang uses a structural type system that maps directly to JSON Schema for AI interactions. Types constrain the shape of data that the LLM must produce.


Primitive Types

string

Represents text values. Maps to JSON Schema { "type": "string" }.

thinklang
let name: string = "Alice"
let greeting = think<string>("Say hello")

int

Represents whole numbers. Maps to JSON Schema { "type": "integer" }.

thinklang
let count: int = 42

float

Represents decimal numbers. Maps to JSON Schema { "type": "number" }.

thinklang
let score: float = 0.95

bool

Represents boolean values (true or false). Maps to JSON Schema { "type": "boolean" }.

thinklang
let active: bool = true

null

Represents the null value. Maps to JSON Schema { "type": "null" }.

thinklang
let nothing: null = null

Named Types (User-Defined)

Declared with the type keyword. Each named type becomes a JSON Schema object with required fields.

thinklang
type Person {
  name: string
  age: int
  email: string?
}

Generated JSON Schema:

json
{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer" },
    "email": {
      "anyOf": [
        { "type": "string" },
        { "type": "null" }
      ]
    }
  },
  "required": ["name", "age"],
  "additionalProperties": false
}

Named types may reference other named types:

thinklang
type Address {
  street: string
  city: string
  country: string
}

type Person {
  name: string
  address: Address
}

Array Types: T[]

Represents an ordered list of elements of type T. Maps to JSON Schema { "type": "array", "items": T }.

thinklang
type Report {
  tags: string[]
  scores: float[]
  people: Person[]
}

Array types can be combined with other type constructors:

thinklang
// Array of optional strings
type Data {
  items: string?[]
}

// Optional array
type Data {
  items: string[]?
}

Optional Types: T?

Indicates a value may be T or null. Optional fields are not included in the JSON Schema required array.

Maps to { "anyOf": [T, { "type": "null" }] }.

thinklang
type Contact {
  name: string
  phone: string?
  email: string?
}

In this example, name is required while phone and email may be null.


Union Types: T | U

A value that may be one of several types. Maps to { "anyOf": [T, U, ...] }.

thinklang
type Result {
  status: string
  value: string | int | null
}

Parentheses may be used for grouping:

thinklang
type Container {
  items: (string | int)[]
}

Confident<T>

Wraps a value with a confidence score and reasoning. When used as a type argument to think, infer, or reason, the LLM must produce all three fields.

thinklang
let result = think<Confident<Sentiment>>("Analyze sentiment")
  with context: review

Generated JSON Schema:

json
{
  "type": "object",
  "properties": {
    "value": { /* schema for T */ },
    "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
    "reasoning": { "type": "string" }
  },
  "required": ["value", "confidence", "reasoning"],
  "additionalProperties": false
}

The result is an instance of the Confident<T> class. See runtime-api.md for available methods.

Confident<T> works with any inner type:

thinklang
// Confident with a primitive
let result = think<Confident<string>>("Translate this text")

// Confident with a named type
let result = think<Confident<Category>>("Classify this item")

// Confident with an array
let result = think<Confident<string[]>>("List the key topics")

Type Annotations

Annotations appear before a field in a type declaration and influence the generated JSON Schema. They guide the LLM to produce values within the specified constraints.

@description(text)

Adds a human-readable description to the field. Maps to the JSON Schema description keyword.

thinklang
type Sentiment {
  @description("positive, negative, or neutral")
  label: string
  @description("Intensity from 1-10")
  intensity: int
}

@range(min..max)

Sets numeric minimum and maximum bounds. The value is a string with .. separating the bounds. Maps to JSON Schema minimum and maximum.

thinklang
type Score {
  @range("0..100")
  value: int
  @range("0.0..1.0")
  confidence: float
}

@minLength(n)

Sets the minimum string length. Maps to JSON Schema minLength.

thinklang
type Post {
  @minLength(10)
  body: string
}

@maxLength(n)

Sets the maximum string length. Maps to JSON Schema maxLength.

thinklang
type Tweet {
  @maxLength(280)
  text: string
}

@minItems(n)

Sets the minimum number of items in an array. Maps to JSON Schema minItems.

thinklang
type Analysis {
  @minItems(1)
  keyPoints: string[]
}

@maxItems(n)

Sets the maximum number of items in an array. Maps to JSON Schema maxItems.

thinklang
type ExtractionResult {
  @maxItems(10)
  people: Person[]
}

@pattern(regex)

Constrains a string to match a regular expression. Maps to JSON Schema pattern.

thinklang
type Contact {
  @pattern("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$")
  email: string
}

Combining Annotations

Multiple annotations can be applied to a single field:

thinklang
type Summary {
  @description("A concise one-line headline")
  @maxLength(100)
  headline: string

  @description("Key takeaways from the text")
  @minItems(2)
  @maxItems(5)
  points: string[]
}

Type Expression Summary

SyntaxCategoryJSON Schema
stringPrimitive{ "type": "string" }
intPrimitive{ "type": "integer" }
floatPrimitive{ "type": "number" }
boolPrimitive{ "type": "boolean" }
nullPrimitive{ "type": "null" }
MyTypeNamedObject schema with fields from type MyType { ... }
T[]Array{ "type": "array", "items": T }
T?Optional{ "anyOf": [T, { "type": "null" }] }
T | UUnion{ "anyOf": [T, U] }
Confident<T>ConfidentObject with value (T), confidence (number), reasoning (string)