This package adds Org-Babel support support for evaluating typescript (and ts alias) code blocks using using ts-node.
Unlike ob-typescript, ob-ts-node works seamlessly with Node.js CommonJS-style imports.
#+BEGIN_SRC typescript :cli-args "--transpile-only"
const https = require('https');
https.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
console.log(JSON.parse(data).title);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
#+END_SRC
#+RESULTS:
: Leopard Spots on Martian Rocks
Note: Unlike Elisp, external languages only return results via stdout. To capture values, you must console.log them.
The project is more or less in beta. But still, one can benefit from using it.
- [X] Basic support for evaluation
- [X] Better support for customization
- [ ] Support for `:session`
Using use-package and quelpa packages (recommended):
(use-package ob-ts-node
:ensure t
:after org
:config
(ob-ts-node-setup)
(add-to-list 'org-babel-load-languages '(ts-node . t))
(org-babel-do-load-languages 'org-babel-load-languages
org-babel-load-languages)
:custom
(ob-ts-node-tsconfig "~/.config/ts-node/tsconfig.json")) ;; Recommended to pin `tsconfig.json`(add-to-list 'load-path "/path/to/ob-ts-node.el")
(require 'ob-ts-node)
(ob-ts-node-setup)
(add-to-list 'org-babel-load-languages '(ts-node . t))
(org-babel-do-load-languages 'org-babel-load-languages
org-babel-load-languages)
(setq ob-ts-node-tsconfig "~/.config/ts-node/tsconfig.json")npm i -g node typescript ts-nodeRecommended: pin a tsconfig.json, as shown in Installation section.
ts-node is sensitive to compiler options. For predictable behavior across Babel blocks, use a project config (per “via tsconfig.json (recommended)”).
Minimal config you can copy:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"esModuleInterop": true
}
}Note: Set strict to false to evade type-errors for easier scenarios
- :cli-args:
Extra flags passed to ts-node:
#+BEGIN_SRC typescript :cli-args "--skip-project" // your code goes here #+END_SRCNote: If
ob-ts-node-tsconfigis set, using--skip-projectwill automatically suppress the injection of that config file. Warning: When skipping the project file, you may need to provide compiler options manually if your environment defaults don’t match the code style (e.g. CommonJS vs ESM)::cli-args "--skip-project --compiler-options '{\"module\":\"commonjs\"}'" - :cli-override:
Completely override the arguments:
#+BEGIN_SRC typescript :cli-override "-v" console.log(43) #+END_SRC #+RESULTS: : v9.1.1 - :cli-cmd
Override the command entirely (default is
ts-node, customizable viaob-ts-node-command):#+BEGIN_SRC ts :cli-cmd "npx tsx" console.log("Using tsx"); #+END_SRC #+RESULTS: : Using tsx
You can swap the runner via :cli-cmd and keep the same Org-Babel flow.
- tsx (zero-config TS/ESM runner)
#+BEGIN_SRC typescript :cli-cmd "npx tsx" console.log("Using npx tsx"); #+END_SRC #+RESULTS: : Using npx tsx - bun (fast JS/TS runtime)
#+BEGIN_SRC typescript :cli-cmd "npx bun run" console.log("Hello from bun"); #+END_SRC #+RESULTS: : Hello from bun - deno (secure runtime; add permissions if needed)
#+BEGIN_SRC typescript :cli-cmd "npx deno run" console.log("Deno here"); #+END_SRC #+RESULTS: : Deno here
- Emacs >= 25.1 (for
alist-get), Org >= 8.0 - Emacs >= 29 uses
typescript-ts-mode; older Emacs falls back totypescript-mode; otherwisejs-mode.
If tsconfig.json isn’t found from the execution directory, ts-node falls back to internal defaults.
Fix: place a project tsconfig.json in the repo root or set ob-ts-node-tsconfig to a known file.
Quick sanity checks:
ts-node --showConfigerror TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.
Solution:
npm i --save-dev @types/nodeerror TS7006: Parameter 'resp' implicitly has an 'any' type.
Solution: use :cli-args "--transpile-only" in babel header