A modern, pragmatic typed superset that compiles to JavaScript — with a clean CLI and first-class developer UX.
VS Code Extension:
Visual Studio Marketplace
•
Open VSX Registry
Docs:
Read the full documentation →
DeltaScript is a small language that compiles to JavaScript. It focuses on:
- Clear and readable syntax.
- Lightweight static types to catch mistakes early.
- Great CLI ergonomics for building, watching, and running single files.
- Friendly logging via SpectralLogs (optional, with shims and fallbacks).
You write .ds files and use the dsc CLI to transpile them into .js (ESM). The CLI also supports running a single .ds directly and can bundle dependencies for convenient execution.
You can install globally or locally.
npm i -g deltascriptor
npm i deltascriptAfter install, the dsc command will be available (globally or via npx/bunx/pnpx):
dsc --helpnpx dsc --helpbunx dsc --help
Initialize a project:
mkdir my-app && cd my-app
dsc init
# creates dsk.config.ds and ensures ./src exists
Add a file:
// ./src/main.ds
func Main() {
spec.log("Hello from DeltaScript")
}Build the project:
dsc build
Watch mode:
dsc dev
Run a single file directly:
dsc ./src/main.ds
When running a single file, dsc compiles to a temporary .mjs and executes it with Node for full interactivity.
dsc init- Creates
dsk.config.ds(default config) and ensuressrc/exists.
- Creates
dsc build [--no-builtins] [--migrate-to-spec] [--minify] [--spectral-cdn]- Transpile all
.dsunderentryinto.jsunderoutDir. --minifywill minify emitted JS (best‑effort via esbuild if available).
- Transpile all
dsc dev [--no-builtins] [--migrate-to-spec] [--spectral-cdn]- Watch mode with per-file debounce and concise logs.
dsc <file.ds> [args...] [--no-builtins] [--migrate-to-spec] [--spectral-cdn]- Transpile a single
.dsand execute it immediately using a temp.mjs. - When possible, the CLI bundles the entry for execution (includes imported
.jsand.ds).
- Transpile a single
--no-builtins- Disables SpectralLogs integration.
The configuration file is a JSON‑like object. Example:
export default {
module: 'cjs',
outDir: 'dist',
entry: 'src',
include: ['src'],
exclude: ['node_modules'],
builtins: true,
minify: false
}entry: root folder to search for.dsfiles.outDir: output folder for.jsfiles.include/exclude: path filters.builtins: enables SpectralLogs integration and gentle tips.minify: when true, builds are minified (same effect as--minify).
See the full guide: Language Docs
Highlights:
-
Variables and types:
let username::str = "Manuel" let score::num = 42 let flags::arr<mbool> = [true, false, maybe] let obj::obj = { debug: true }
-
Functions (
funcoverfunction):func Greet(person::str) { spec.log("Hola " + person + "!") }
-
Function return types:
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
- Annotate after the parameter list with
::ReturnType. - The compiler checks each
returnagainst the declared type and also reports missing returns. - Object literal returns for interface types are validated against required fields (shallow).
- Annotate after the parameter list with
-
Default parameters and type parsing:
func Main(x::num = 3) { spec.log("types " + x) }
-
Classes:
class Counter { constructor(initial::num) { this.count::num = initial } increment() { this.count = this.count + 1 } toString()::str { return "Counter(" + String(this.count) + ")" } } let c::Counter = new Counter(2) let s::str = c.toString() // class method return type is enforced
-
Class/Function return types with
::ReturnTypeare enforced:- Mismatched return expressions report diagnostics.
- Missing
returnwhen a non-void is declared is reported.
-
Control flow:
let i::num = 0 for (i = 0; i < 3; i = i + 1) { spec.log("Iteración for:", i) } let w::num = 0 while (w < 2) { spec.log("Iteración while:", 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") }
-
Mutability controls (
mut/inmut):let username::str = "Manuel" let score::num = 42 mut score = 50 // explicit mutation assignment (allowed while variable is mutable) inmut username // from this point on, username becomes immutable (const) // After inmut, further mutations are not allowed and `mut username = ...` will error.
-
Interfaces (custom types):
interface Person { name::str; age::num; tags::arr<str>; meta::obj; } func processPerson(p::Person) { spec.log("Procesando:", p.name) return p.name } let person::Person = { name: "Luisa", age: 21, tags: ["dev","student"], meta: {} } processPerson(person)
- Optional fields with
?:interface Product { id::num; name::str; price::num; inStock::mbool; module?:: "esm" | "cjs"; // optional }
- Unions and string literals in field types are supported (e.g.,
"esm" | "cjs" | str). - Per-field validation at declaration time ensures each provided property matches its field type.
mboolacceptstrue,false, andmaybe(treated as a boolean-like literal).- Arrays with generics (e.g.,
arr<str>) are supported as before. - Comments are ignored by validators (lines starting with
//and blocks/* ... */).
Examples:
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"DeltaScript provides optional SpectralLogs integration in three modes:
-
Package imports (preferred when available):
import spec from 'spectrallogs'import specweb from 'spectrallogs/web'
-
CDN imports (force with
--spectral-cdn):import spec from "https://esm.sh/spectrallogs"import specweb from "https://esm.sh/spectrallogs/web"
-
Shim fallback (no install, no CDN):
- Defines
spec(logging methods + asyncinput) and an emptyspecweb. - No top‑level await is used;
inputusesreadline/promiseswhen available, orwindow.promptin the browser.
- Defines
Notes:
- DeltaScript no longer emits automatic console usage warnings. If you want to migrate
console.*tospec.*, use the--migrate-to-specflag.
See Examples for complete samples, including:
- Arrays and objects
- Functions and classes
- Control flow
- Interfaces and typed arrays
- Try/catch/finally
- Logging via
spec.*
- Emitted JS is ESM. In project builds it writes
.jstooutDir. - Single-file runs compile to a temporary
.mjsand execute via Node, preserving interactivity (e.g.,await spec.input(...)). - Single-file runner attempts to bundle dependencies (both
.dsand.js) for convenience using esbuild, when available.
- You can import
.jsmodules from.dsfiles. In project builds they are preserved. - In single-file runs, the runner bundles imported
.jsalong with transpiled.dsto a single executable module when possible. - Watch mode (
dsc dev) recompiles changed files with debounce and concise output.
MIT
- Install the DeltaScript extension for best DX (syntax, LSP, completion, hover, go to definition):
- You can also search for “deltascript” directly inside VS Code in either the Marketplace or Open VSX (if using a compatible VS Code build).
What you get:
- Syntax highlighting: keywords, types, function and member calls, constants (
maybe/true/false), and::Typeannotations. - Inline diagnostics backed by the DeltaScript transpiler:
- Syntax errors and DeltaScript type errors with red squiggles and entries in the Problems panel.
- Multiple diagnostics per file supported.
- Smarter completions: keywords (including async/await), types and constants,
spec.*helpers, in-scope identifiers, and snippets. - Hovers with code previews for symbol definitions and concise keyword/tooltips (mut, inmut, func, interface, spec.*).
- Navigation: go to definition, document/workspace symbols, references, rename, and signature help.
Tip: you can also search for “deltascript” directly inside VS Code.
