An online REPL for JavaScript/TypeScript.
- Interactively execute
anyalmost any JavaScript/TypeScript code directly in your browser. - (Type annotations are stripped before execution, and no type checking is performed.)
- Beautiful output with syntax highlighting (powered by highlight.js) and pretty-printing (enabled by showify).
- Import any NPM package directly with
importstatements (powered by jsdelivr). - Auto-completion (intellisense) powered by the TypeScript language service running in a Web Worker. Third-party type definitions are automatically fetched when importing NPM packages (powered by @typescript/ata).
- Shareable links to your REPL, with history encoded in the URL.
- Top-level
awaitis supported, and can be cancelled using Ctrl + C. - Conveniently copy and jump to previous inputs using the buttons on the right side of the input field, and easily navigate through your history with the ↑ and ↓ keys.
- REPL commands for extra functionality:
:check <code>or:c <code>to get the type of an expression without executing it.:type <TypeExpr>or:t <TypeExpr>to get the evaluated type of a TypeScript type expression.
- Clear history with
clear()orconsole.clear(). - Full support for the
consoleAPI, including methods likeconsole.dir(),console.group(),console.table(),console.time(), etc. - Responsive layout, optimized for mobile devices.
This REPL simulates rather than implements a true global scope, which affects how closures work between separate evaluations. For example:
const f = () => value; // First evaluation
const value = 42; // Second evaluation
f(); // Third evaluation - ReferenceError!Behavior explanation:
- When pasted as a single block, this code works as expected because it’s evaluated together.
- When run line-by-line, it fails because each line is evaluated in its own isolated context.
Technical details: Each code snippet is processed as follows:
- The TypeScript compiler API analyzes the code.
- Top-level variables are extracted to a shared context object.
- This context is passed to subsequent evaluations.
This effectively transforms the above example into something like:
const context = {};
const updateContext = (obj) => {
for (const key in obj) {
context[key] = obj[key];
}
};
updateContext(
new Function(
...Object.keys(context),
`
const f = () => value;
return { f };
`,
)(...Object.values(context)),
);
updateContext(
new Function(
...Object.keys(context),
`
const value = 42;
return { value };
`,
)(...Object.values(context)),
);
updateContext(
new Function(
...Object.keys(context),
`
const __repl_result___ = f();
return { __repl_result___ };
`,
)(...Object.values(context)),
);
console.log(context.__repl_result___);Since the value variable is not defined in the first snippet of code, the f function will throw a ReferenceError when it’s called.
