Language Guide 
DeltaScript is a typed superset that compiles to JavaScript (ESM). This guide highlights the core syntax and typing model.
Files and Modules 
- File extension: 
.ds - Emitted JavaScript: 
.js(ESM) when building;.mjstemp when running a single file. - Imports/exports follow JavaScript semantics (compiler preserves them).
 
Types and Annotations 
Attach types with ::.
- Primitives: 
num,str - Logical maybe: 
mbool→ true/false/maybe (runtime may treatmaybeas nondeterministic) - Arrays: 
arr, generic arrays:arr<T> - Objects: 
obj - Custom interfaces/classes: use their identifier
 
Examples:
ts
let n::num = 3
let s::str = "hello"
let maybeFlag::mbool = maybe
let flags::arr<mbool> = [true, false, maybe]
let bag::arr = [1, "a", true]  # untyped array
let cfg::obj = { debug: true }Extended interface typing 
- Optional fields with 
?are supported:tsinterface Product { id::num; name::str; price::num; inStock::mbool; module?:: "esm" | "cjs"; // optional } - Union and string-literal types in fields are allowed (e.g., 
"esm" | "cjs" | str). - Per‑field validation at declaration checks that each provided property matches its field type (shallow).
 mboolacceptstrue,false, andmaybe.- Comments are ignored by validators (lines starting with 
//and blocks/* ... */). 
Examples:
ts
let ok1::Product = { id: 1, name: "Laptop", price: 999.99, inStock: true, module: "cjs" };
let ok2::Product = { id: 2, name: "Mouse", price: 29.99, inStock: maybe };
let bad1::Product = { id: 3, name: "Cable", price: "9.99", inStock: true }; // error: price expects num
let bad2::Product = { id: 4, name: "Hub", price: 19.99, inStock: true, module: "commonjs" }; // error: module expects "esm" | "cjs"Mutability: mut / inmut 
inmut <var>: marks an existingletvariable as immutable from that point forward (like turning it into a const). Further reassignments ormut <var> = ...become errors.mut <var> = <expr>: explicit mutation assignment, allowed only while the variable is still mutable.
Examples:
ts
let username::str = "Manuel"
let score::num = 42
mut score = 50          // allowed (score is still mutable)
inmut username          // from here, username cannot change
// This will error because username is now immutable:
// mut username = "Other"Reassignment must conform to the declared type.
Functions 
Use func instead of function.
ts
func Sum(a::num, b::num) {
  return a + b
}
func Main(x::num = 3) {
  spec.log("x:", x)
}- Default values are supported. The compiler correctly infers the type ignoring the default literal in the type signature.
 - Return types are inferred; explicit annotations are optional.
 
Function return types 
You can explicitly annotate a function's return type after the parameter list using ::ReturnType.
ts
func Sum(a::num, b::num)::num {
  return a + b
}
func Wrong()::num {
  return "x"        //error: Return type mismatch (expects num)
}
func NoReturn()::str {
  let x = 1
}                    // error: declares return type str but has no return- The compiler validates every 
returnexpression against the declared return type. - Missing return is reported at the 
::ReturnTypeposition. - When returning an object literal for an interface type, required fields are validated (shallow check):
 
ts
interface Person { name::str; age::num; }
func Make()::Person {
  return { name: "A" }    // error: expects Person (missing required: age)
}Classes 
ts
class Counter {
  constructor(initial::num) {
    this.count::num = initial
  }
  inc() { this.count = this.count + 1 }
  add(n::num) { this.count = this.count + n }
  toString()::str { return "Counter(" + String(this.count) + ")" }
}
let c::Counter = new Counter(2)
c.inc()
c.add(5)
let s::str = c.toString()   // method return type is enforcedMethod return types 
- Methods can declare 
::ReturnTypejust like functions. The compiler validates eachreturninside the method. - Calls to class methods use the declared return type for type inference, even when chained from 
new Class(...).method(). 
Ternary inference and string concatenation 
- The compiler infers the type of 
cond ? a : bfrom its branches (not from the condition). +concatenations that include a string literal or.toString()are inferred asstr.- Common built‑ins are recognized during inference: 
parseFloat/parseInt/Number → num,String/JSON.stringify → str,Boolean/Array.isArray → mbool,Math.* → num. 
Control Flow 
ts
let i::num = 0
for (i = 0; i < 3; i = i + 1) {
  spec.log("for i:", i)
}
let w::num = 0
while (w < 2) {
  spec.log("while w:", w)
  w = w + 1
}
let opt::str = "B"
if (opt === "A") {
  spec.log("Option A")
} else if (opt === "B") {
  spec.log("Option B")
} else {
  spec.log("Default")
}Interfaces 
Interfaces describe object shapes.
ts
interface Person {
  name::str;
  age::num;
  tags::arr<str>;
  meta::obj;
}
func processPerson(p::Person) {
  spec.log("Procesando:", p.name)
  return p.name
}Errors and Code Frames 
The CLI shows concise errors with code frames, including line/column and colorized output. In single‑file runs, errors show a frame for the source file.
Logging 
Use spec.* for logging (see SpectralLogs doc). You can still use console.*, but the CLI will suggest spec.* for a consistent experience. A migration flag exists to rewrite automatically.
