⚠️ Warning: This project is not yet stable and may undergo significant changes before reaching version 1.0.0. We strongly advise against using it in production environments.
TypeScript ergonomics, Rust performance, compiled to native. A typed, TypeScript-flavored language (
.ts) that compiles to native binaries via idiomatic Rust (wasm/napioutputs planned).
| Package | Version | Description |
|---|---|---|
| dashscript | The ds toolchain in one package — translates oxc AST → Rust, package.json → Cargo.toml, bindgen, CLI, editor types. |
# one package — provides the `ds` command
$ pnpm add -g dashscript
# or as a standalone binary
$ cargo install dashscriptNo separate Rust install. DashScript manages its own pinned Rust toolchain — downloaded on first use like an npm dependency — so
pnpm add dashscriptis all you need.
// main.ts — TypeScript-flavored source
function greet(name: string): string {
return `Hello, ${name}!`;
}
const message: string = greet("DashScript");$ ds main.ts # run a file directly (like `node a.js`)
$ ds build main.ts # → dist/<name> — a native binary (default)
$ ds build main.ts --target rust # → dist/<name>/ — the translated Rust crateds main.ts runs a .ts file directly — translate → compile (cached) → run, like node a.js. ds build parses .ts with oxc, translates the AST to idiomatic Rust, and ships a native binary in dist/<name>. Pass --target rust to stop at the translated crate instead:
// generated by DashScript (--target rust)
fn greet(name: &str) -> String {
format!("Hello, {name}!")
}
fn main() {
let message: String = greet("DashScript");
}$ ds run <script> # run a package.json script (like `pnpm run`)ds run runs a shell command from package.json scripts through the system shell, like pnpm run. (ds run is always explicit — running a file is ds <file.ts>.)
DashScript projects use a package.json — the one manifest every JS tool already reads. Standard npm fields map straight to cargo: bin declares executables (one project compiles to several binaries); main → [lib]; Rust crate deps under dashscript.cargo.dependencies → [dependencies] (npm dependencies stay JS deps, never reaching Cargo.toml). On ds build, the package lowers to a Cargo.toml:
{
"name": "my-app",
"bin": {
"serve": "serve.ts",
"migrate": "migrate.ts"
},
"dashscript": {
"target": "bin",
"cargo": {
"dependencies": {
"serde": "1.0",
"tokio": "1.0"
}
}
}
}# fetch the crate — no .d.ts stub; types come straight from the crate source
$ ds add cargo:serdeds add cargo:<crate> fetches the crate and records it in package.json, with no .d.ts stub — Rust is statically typed, so the crate's own source (in ~/.cargo) is the complete type truth, read directly by the editor the way rust-analyzer reads its deps. For a local Rust file, ds add <file>.rs runs bindgen to emit a .d.ts beside it. No separate ds gen step.
ds check is the composite — translatability plus a format check (vp check style); ds lint checks translatability alone; ds fmt formats in place. With no argument each runs over every .ts in the project, and ds check --fix writes the fix. All built in-process on the parsed AST (no external oxlint/oxfmt):
$ ds check # lint + format check, whole project (like `vp check`)
$ ds check --fix # ...and write formatting fixes
$ ds lint # translatability check only
$ ds fmt # format every .ts in placeThe emitted Rust is finally verified with cargo check / cargo clippy on the generated project.
DashScript maps a TypeScript-flavored surface to Rust semantics, growing incrementally as real demand drives each mapping — never speculatively.
- Language coverage — the full Rust type/memory-safety model (ownership, borrowing, lifetimes, traits), with TypeScript as the presentation only. Today: a safe TS→Rust subset (auto clone/borrow/narrowing bridge the gaps).
- Standard libraries — ES built-ins (
Math/String/Array/Object/Number, … — largely mapped today), then thenode:stdlib (node:crypto,node:zlib,node:fs, …). Web APIs are tracked separately under WinterTC below. - Compatibility — degrade, don't reject — a construct the static translator can't lower runs under an embedded QuickJS engine at the function granularity (inheriting full ECMAScript semantics) instead of failing, so existing TS/JS keeps working without a rewrite. Reflection (
typeof/instanceof/Object.keys) resolves at compile time where the type is known — zero-cost, no dynamic value model — so only the residual dynamic cases degrade. - WinterTC Minimum Common Web API — the Ecma TC55 (formerly WinterCG) Minimum Common Web Platform API (shared by Node, Deno, Bun, Cloudflare Workers), on the same static-first + per-function degrade model as the ECMAScript core: each Web API maps to a Rust crate first (static, zero-cost), and an edge the static translator cannot lower takes the per-function engine path with the Web API registered as a builtin (same Rust impl). Synchronous APIs map first (URL,
URLSearchParams,TextEncoder,Headers,Blob,FormData,SubtleCrypto, … today); asynchronous ones (fetch,setTimeout, Streams) introduce a tokio runtime and a thread model. Conformance is a WPT subset, run static-first with per-function engine degrade (mirroring test262). - More outputs —
wasmandnapitargets (Rust compiled to WebAssembly / napi-rs), so.tsships to the web and Node ecosystems. The static segment (including compile-time reflection) lowers to plain wasm — no engine bundled for the common case; only the degraded minority pulls in QuickJS-wasm (Javy provesrquickjscompiles towasm32-wasip1). - Developer experience —
ds test, editor/LSP integration, conformance fixtures. - Self-hosting (north star) — rewrite the toolchain in
.tsitself, reachingoxc(and any Rust crate) through bindgen.
- Node.js 18.x or higher
- pnpm 9.x or higher (recommended package manager)
- Rust — managed by DashScript (a pinned toolchain is downloaded on demand); no separate install needed to use DashScript
- Git for version control
-
Clone the repository:
git clone https://github.com/DemoMacro/dashscript.git cd dashscript -
Install dependencies:
pnpm install
-
Build all packages:
pnpm build
pnpm build # Build all packages
cd packages/<pkg> && pnpm build # Build one package
vp check # Lint & formatWe welcome contributions! See CONTRIBUTING.md for the full contribution workflow, coding standards, and PR checklist.
This project is licensed under the MIT License - see the LICENSE file for details.
Built with ❤️ by Demo Macro