TypeScript Sandbox

A DOM library for interacting with TypeScript and JavaScript code, which powers the heart of theTypeScript playground

You can use the TypeScript sandbox for:

  • Building IDE-like experiences for people to explore your library's API
  • Building interactive web tools which use TypeScript, with a lot of the Playgrounds developer experience for free

For example, the sandbox to the side has grabbed the Types forDangerJS with no modifications for this code sample. This is because the Playground's Automatic Type Acquisition is enabled by default. It will also look for the same parameters for code, and selection indexes inside the URL.

Try clickingthis URL to see that in action.

This library builds on top of theMonaco Editor, providing a higher level API but offering access to all the lower-level APIs via a singlesandbox object.

You can find the code for the TypeScript Sandbox inside themicrosoft/TypeScript-Website mono-repo.

Downloading Sandbox...

Usage

A sandbox uses the same tools as monaco-editor, meaning this library is shipped as an AMD bundle which you can use theVSCode Loader torequire.

Because we need it for the TypeScript website, you can use our hosted copyhere.

Get Started

Create a new file:index.html and paste this code into that file.

<!DOCTYPE html><html lang="en">  <head>    <meta charset="utf-8" />  </head>  <div id="loader">Loading...</div>  <div id="monaco-editor-embed" style="height: 800px;" />  <script>    // First set up the VSCode loader in a script tag    const getLoaderScript = document.createElement('script')    getLoaderScript.src = 'https://www.typescriptlang.org/js/vs.loader.js'    getLoaderScript.async = true    getLoaderScript.onload = () => {      // Now the loader is ready, tell require where it can get the version of monaco, and the sandbox      // This version uses the latest version of the sandbox, which is used on the TypeScript website      // For the monaco version you can use unpkg or the TypeSCript web infra CDN      // You can see the available releases for TypeScript here:      // https://playgroundcdn.typescriptlang.org/indexes/releases.json      //      require.config({        paths: {          vs: 'https://playgroundcdn.typescriptlang.org/cdn/4.0.5/monaco/min/vs',          // vs: 'https://unpkg.com/@typescript-deploys/monaco-editor@4.0.5/min/vs',          sandbox: 'https://www.typescriptlang.org/js/sandbox',        },        // This is something you need for monaco to work        ignoreDuplicateModules: ['vs/editor/editor.main'],      })      // Grab a copy of monaco, TypeScript and the sandbox      require(['vs/editor/editor.main', 'vs/language/typescript/tsWorker', 'sandbox/index'], (        main,        _tsWorker,        sandboxFactory      ) => {        const initialCode = `import {markdown, danger} from "danger"export default async function () {    // Check for new @types in devDependencies    const packageJSONDiff = await danger.git.JSONDiffForFile("package.json")    const newDeps = packageJSONDiff.devDependencies.added    const newTypesDeps = newDeps?.filter(d => d.includes("@types")) ?? []    if (newTypesDeps.length){        markdown("Added new types packages " + newTypesDeps.join(", "))    }}`        const isOK = main && window.ts && sandboxFactory        if (isOK) {          document.getElementById('loader').parentNode.removeChild(document.getElementById('loader'))        } else {          console.error('Could not get all the dependencies of sandbox set up!')          console.error('main', !!main, 'ts', !!window.ts, 'sandbox', !!sandbox)          return        }        // Create a sandbox and embed it into the div #monaco-editor-embed        const sandboxConfig = {          text: initialCode,          compilerOptions: {},          domID: 'monaco-editor-embed',        }        const sandbox = sandboxFactory.createTypeScriptSandbox(sandboxConfig, main, window.ts)        sandbox.editor.focus()      })    }    document.body.appendChild(getLoaderScript)  </script></html>

Opening the fileindex.html in a web browser will load up the same sandbox up at the top of the page.

Some examples of the API

Converting the user's TypeScript into JavaScript

const sandbox = createTypeScriptSandbox(sandboxConfig, main, ts)// Async because it needs to go  const js = await sandbox.getRunnableJS()console.log(js)

Get the DTS for the user's editor

const sandbox = createTypeScriptSandbox(sandboxConfig, main, ts)const dts = await sandbox.getDTSForCode()console.log(dts)

Make a request for an LSP response

const sandbox = createTypeScriptSandbox(sandboxConfig, main, ts)// A worker here is a web-worker, set up by monaco-typescript// which does the computation in the background const worker = await sandbox.getWorkerProcess()const definitions =  await client.getDefinitionAtPosition(model.uri.toString(), 6)

Change compiler flags using a few different APIs

const sandbox = createTypeScriptSandbox(sandboxConfig, main, ts)// Hook in to all changes to the compilersandbox.setDidUpdateCompilerSettings((newOptions) => {  console.log("Compiler settings changed: ", newOptions)})// Update via key valuesandbox.updateCompilerSetting("allowJs", true)// Update via an objectsandbox.updateCompilerSettings({ jsx: 0 })// Replace the compiler settingssandbox.setCompilerSettings({})

Highlight some code in the editor

const sandbox = createTypeScriptSandbox(sandboxConfig, main, ts)const start = {  lineNumber: 0,  column: 0}const end = {  lineNumber: 0,  column: 4}const decorations = sandbox.editor.deltaDecorations([], [  {    range: new sandbox.monaco.Range(start.lineNumber, start.column, end.lineNumber, end.column),    options: { inlineClassName: 'error-highlight' },  },])

Create your own playground.

const sandbox = createTypeScriptSandbox(sandboxConfig, main, ts)// Use a script to make a JSON file like:// { //   "file:///node_modules/types/keyboard/index.d.ts": "export const enterKey: string"// }//// Where the keys are the paths, and the values are the source-code. The sandbox// will use the node resolution lookup strategy by default.const dtsFiles = {} Object.keys(dtsFiles).forEach(path => {  sandbox.languageServiceDefaults.addExtraLib(dts[path], path);});

The API is mainly a light shim over themonaco-editor API with themonaco-typescript API.