# How to run TypeScript code in a sandbox Write the `.ts` file into an isolated microVM and run it with Node.js type stripping or Bun, both already installed, with no build step. **On Runtime, there is nothing to install. Node.js 24.21.0 and Bun 1.4.0 are in every sandbox, and both run a `.ts` file directly.** Each sandbox is a Firecracker microVM with its own kernel. A coding agent can therefore test each TypeScript snippet it writes in a new sandbox. The code interpreter adds a stateful TypeScript session. ## Three ways to run it | Way | Command | Type checks? | Notes | | ---------------------- | ------------------------ | ------------ | --------------------------------------------------------- | | Node.js type stripping | `node job.ts` | No | Erasable syntax only; imports need the `.ts` extension | | Bun | `bun job.ts` | No | Transpiles every file on the fly, TSX included | | Code interpreter | `language: "typescript"` | No | Keeps variables between cells; in the default image | | TypeScript compiler | `npx tsc --noEmit` | Yes | Installs `typescript` from npm (7.0.2 on 26 October 2026) | Node.js runs files that contain only erasable TypeScript syntax by default since v22.18.0 and v23.6.0, and the feature is marked stable from v24.12.0. It replaces types with whitespace and does no type checking. Enums, namespaces with runtime code, parameter properties, import aliases and decorators are refused ([Node.js](https://nodejs.org/api/typescript.html)). Bun "transpiles every file on the fly with its native transpiler before running it" ([Bun](https://bun.com/docs/runtime)), so those forms work there. ## Run a TypeScript file ```ts import { Sandbox } from "withruntime"; const source = ` type Point = { x: number; y: number }; const dist = (a: Point, b: Point): number => Math.hypot(a.x - b.x, a.y - b.y); console.log(dist({ x: 0, y: 0 }, { x: 3, y: 4 })); `; await using sbx = await Sandbox.create({ network: { internet: false }, timeoutSeconds: 300, onLeaseEnd: "stop", }); await sbx.files.write("/workspace/job.ts", source); const node = await sbx.exec(["node", "job.ts"], { timeoutMs: 20_000 }); const bun = await sbx.exec(["bun", "job.ts"], { timeoutMs: 20_000 }); console.log(node.stdout, bun.stdout); // 5 and 5 ``` ```python from withruntime import Sandbox source = """ type Point = { x: number; y: number }; const dist = (a: Point, b: Point): number => Math.hypot(a.x - b.x, a.y - b.y); console.log(dist({ x: 0, y: 0 }, { x: 3, y: 4 })); """ with Sandbox.create(network={"internet": False}, timeout_seconds=300, on_lease_end="stop") as sbx: sbx.files.write("/workspace/job.ts", source) node = sbx.exec(["node", "job.ts"], timeout_ms=20_000) bun = sbx.exec(["bun", "job.ts"], timeout_ms=20_000) print(node.stdout, bun.stdout) # 5 and 5 ``` Pass the command as an array. No shell parses the path or the arguments. ## Type-check what a model wrote Running TypeScript does not check types. To reject code that fails type checks, install the compiler once, turn the network off, then check each answer: ```ts check import { Sandbox } from "withruntime"; await using sbx = await Sandbox.create({ network: { internet: true, allow: ["registry.npmjs.org"] }, timeoutSeconds: 900, onLeaseEnd: "stop", }); await sbx.exec("npm init -y && npm install --no-fund --no-audit typescript", { check: true, timeoutMs: 180_000, }); await sbx.network.set({ internet: false }); await sbx.files.write("/workspace/answer.ts", "const n: number = 'seven';\nconsole.log(n);"); const tsc = await sbx.exec(["npx", "tsc", "--noEmit", "--strict", "answer.ts"], { timeoutMs: 60_000, }); if (tsc.exitCode !== 0) console.log("type errors:\n" + tsc.stdout + tsc.stderr); else console.log((await sbx.exec(["node", "answer.ts"], { timeoutMs: 20_000 })).stdout); ``` ```python check from withruntime import Sandbox with Sandbox.create( network={"internet": True, "allow": ["registry.npmjs.org"]}, timeout_seconds=900, on_lease_end="stop", ) as sbx: sbx.exec("npm init -y && npm install --no-fund --no-audit typescript", check=True, timeout_ms=180_000) sbx.network.set(internet=False) sbx.files.write("/workspace/answer.ts", "const n: number = 'seven';\nconsole.log(n);") tsc = sbx.exec(["npx", "tsc", "--noEmit", "--strict", "answer.ts"], timeout_ms=60_000) if tsc.exit_code != 0: print("type errors:\n" + tsc.stdout + tsc.stderr) else: print(sbx.exec(["node", "answer.ts"], timeout_ms=20_000).stdout) ``` Return the compiler's errors to the model unchanged. Run the code only after it passes the type check. ## A TypeScript notebook ```ts check import { Sandbox } from "withruntime"; await using sbx = await Sandbox.create({ network: { internet: false } }); await sbx.interpreter.run("const prices: number[] = [3.5, 2.25, 4]", { language: "typescript" }); const cell = await sbx.interpreter.run("prices.reduce((a, b) => a + b, 0)", { language: "typescript", }); console.log(cell.results[0]?.data["text/plain"]); // 9.75 ``` ```python check from withruntime import Sandbox with Sandbox.create(network={"internet": False}) as sbx: sbx.interpreter.run("const prices: number[] = [3.5, 2.25, 4]", language="typescript") cell = sbx.interpreter.run("prices.reduce((a, b) => a + b, 0)", language="typescript") print(cell["results"][0]["data"]["text/plain"]) # 9.75 ``` TypeScript is in the default image, so the first cell starts without an install ([code interpreter](/docs/javascript#code-interpreter)). ## A project with a `tsconfig.json` Upload the project, install its dependencies, and run its own scripts. Build an image with the compiler and your usual tools once, so each sandbox skips the install step: ```ts check import { Runtime } from "withruntime"; const runtime = new Runtime(); await runtime.images.build({ name: "ts", recipe: { npm: ["typescript", "tsx"] } }); await using sbx = await runtime.sandboxes.create({ image: "ts", timeoutSeconds: 1800 }); await sbx.files.upload("./my-project", "/workspace/app"); await sbx.exec("cd app && npm ci && npx tsc --noEmit && npm test", { check: true, timeoutMs: 900_000, onStdout: (text) => process.stdout.write(text), }); ``` ```python check import sys from withruntime import Runtime runtime = Runtime() runtime.images.build(name="ts", recipe={"npm": ["typescript", "tsx"]}) with runtime.sandboxes.create(image="ts", timeout_seconds=1800) as sbx: sbx.files.upload("./my-project", "/workspace/app") sbx.exec("cd app && npm ci && npx tsc --noEmit && npm test", check=True, timeout_ms=900_000, on_stdout=sys.stdout.write) ``` The host code is TypeScript too. `withruntime` runs on Node 22.12 or later and Bun. `await using` deletes the sandbox when the block ends. To stop the sandbox instead and keep its disk, pass `keep: true` to `create` ([JavaScript SDK](/docs/javascript)). ## Related - [Run JavaScript and Node.js code in a sandbox](/languages/javascript) - [Run Bun in a sandbox](/languages/bun) - [Run Deno code in a sandbox](/languages/deno) - [A coding agent's sandbox](/use-cases/coding-agent-sandbox) - [What is a code interpreter?](/glossary/code-interpreter) ```bash no-run npx withruntime sandboxes run -- bun --version ``` A new account gets 100 free hours of a 1 GB machine in its first 30 days, with no card required. ## Sources - Node.js, TypeScript type stripping: https://nodejs.org/api/typescript.html (read 26 October 2026) - Bun runtime: https://bun.com/docs/runtime (read 26 October 2026) - npm registry, `typescript` latest version 7.0.2: https://registry.npmjs.org/typescript/latest (read 26 October 2026) Facts on this page were checked on 26 October 2026.