65

Is it possible to embed TypeScript code in a web page? I want to embed TypeScript code inside script tags, like this (so that it is automatically compiled to Javascript):

<script type = "text/typescript">
    //TypeScript code goes here
</script>
3
  • 3
    It's possible if you use a run-time compiler, but why in the world would you want to? TypeScript is designed to compile to JavaScript, and translating it at run-time will give you a performance hit. Commented Dec 24, 2012 at 0:42
  • 1
    @PeterOlson There are already some JavaScript libraries that can compile TypeScript to JavaScript (as mentioned below). Are they both considered to be "runtime compilers"? Commented Dec 24, 2012 at 0:46
  • Yes, those are runtime compilers Commented Dec 24, 2012 at 1:08

5 Answers 5

31

Actually there are several projects that allow you to use TypeScript code like that - TypeScript Compile, ts-htaccess.

The catch here is that .ts code should be compiled into JavaScript - it can be done either at client-side (slow; the whole TSC should be loaded into the client as well) or at server-side (obviously faster, and it's far easier to leverage the cache on the compiled code).

Sign up to request clarification or add additional context in comments.

Comments

19

This is a version I wrote that directly uses the version from Microsoft/TypeScript/master so it always stays up to date: https://github.com/basarat/typescript-script

You can even point ts to any other TypeScript version you might have and it will work fine 🌹

1 Comment

Any idea what typescriptServices.js is now? https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js no longer exists. And I can't find anything like it at https://github.com/microsoft/TypeScripthttps://github.com/microsoft/TypeScript. The module migration March 2023 probably changed it all.
6

A JavaScript library has already been developed for this purpose - it's called TypeScript Compile, and it allows typescript to be embedded in HTML (as shown above.)

3 Comments

Please consider the implications of this before you use it - it is an awesome project, but will slow down your website if you use it for a production app or site.
@SteveFenton I only intend to use it for the purpose of testing my Typescript code.
Grand - perfect use of a browser-based compiler!
1

Here's an example of both typescript and SCSS embedded based on my answer in Is there a way to compile SASS to CSS without NodeJS?

Given the following HTML file which has TypeScript in a src and also embedded. I have added comments to flag the parts of note in the HTML file.

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Embedded Typescript and SCSS</title>
    <link rel="stylesheet" type="text/x-scss" href="year-month-input.scss" />
    <style type="text/x-scss">
        #sample {
            th {
                font-family: sans-serif;
            }
        }
    </style>
    <!--
      This JSON in the script block specifies where to find the module files
      that is used for imports in typescript
    -->
    <script type="importmap">
    {
      "imports": {
        "immutable": "https://unpkg.com/immutable@^4.0.0",
        "sass": "https://unpkg.com/sass@^1.63.0/sass.default.js",
        "date-fns": "https://cdn.jsdelivr.net/npm/date-fns@latest/index.mjs"
      }
    }
    </script>
    <script type="application/typescript">
        import {format} from "date-fns";
        const elem = document.getElementById("date") as HTMLTableCellElement;
        elem.innerText = format(Date.now(), "MM/dd/yyyy");
    </script>
    <script type="application/typescript" src="set-date.ts"></script>
    <!--
      This is supposedly needed for Safari to use importmaps
    -->
    <script async
      src="https://unpkg.com/es-module-shims@^1.7.0" 
      crossorigin="anonymous"></script>
    <!--
      This loads up the typescript engine.
    -->
    <script src="https://cdn.jsdelivr.net/npm/typescript@latest"></script>
    <!--
      This is the loader
    -->
    <script type="module" src="embed-scss-typescript.js"></script>
</head>

<body>
    <table id="sample">
        <tr>
            <th><label for="year">Limit</label></th>
            <td class="year-month-input">
                <div class="input-group">
                    <input id="year" type="number" min="0" name="year">
                    <label for="year">years</label>
                </div>
                <div class="input-group">
                    <input id="month" type="number" min="0" name="month">
                    <label for="month">months</label>
                </div>
            </td>
        </tr>
        <tr>
            <th>Date</th>
            <td id="date">{placeholder}</td>
            <td id="date-from-src">{placeholder}</td>
        </tr>
    </table>
</body>

</html>

The loader script embed-scss-typescript.js is as follows:

// @ts-check
// @ts-ignore
import * as sass from "sass";

document.addEventListener("DOMContentLoaded", async () => {
  /**
   *
   * @param {string} scssText
   * @returns {Promise<HTMLStyleElement>}
   */
  const buildCssStyleElementFromScss = async (scssText) => {
    const sassResult = await sass.compileStringAsync(scssText);
    const cssElement = document.createElement("style");
    cssElement.innerHTML = sassResult.css;
    return cssElement;
  };

  /**
   *
   * @param {string} typescriptSource
   * @returns {HTMLScriptElement}
   */
  const buildScriptElementFromTypeScript = (typescriptSource) => {
    const scriptSource = /** @type {any} */ (window).ts.transpile(
      typescriptSource,
      {
        target: "es2015",
      }
    );
    const scriptElement = document.createElement("script");
    scriptElement.type = "module";
    scriptElement.innerHTML = scriptSource;
    return scriptElement;
  };

  /** @type {NodeListOf<HTMLLinkElement|HTMLStyleElement>} */
  const scssElements = document.querySelectorAll(
    "link[rel='stylesheet'][type='text/x-scss'], style[type='text/x-scss']"
  );

  scssElements.forEach(async (scssElement) => {
    /** @type {string} */
    let scssText = "";
    if (scssElement.tagName === "LINK") {
      const fetched = await fetch(
        /** @type {HTMLLinkElement} */ (scssElement).href
      );
      if (fetched.ok) {
        scssText = await fetched.text();
      }
    } else {
      // should be STYLE
      scssText = scssElement.innerHTML;
    }
    const cssElement = await buildCssStyleElementFromScss(scssText);
    scssElement.replaceWith(cssElement);
  });

  /** @type {NodeListOf<HTMLScriptElement>} */
  const typescriptElements = document.querySelectorAll(
    "script[type='application/typescript']"
  );
  typescriptElements.forEach(async (typescriptElement) => {
    /** @type {string} */
    let typescriptSource = "";
    if (typescriptElement.src) {
      const fetched = await fetch(typescriptElement.src);
      if (fetched.ok) {
        typescriptSource = await fetched.text();
      }
    } else {
      typescriptSource = typescriptElement.innerText;
    }
    const scriptElement = buildScriptElementFromTypeScript(typescriptSource);
    typescriptElement.remove();
    document.body.append(scriptElement);
  });
});

As a caveat, this should only be used for quickly experimenting with things locally and shouldn't be used for full websites as it loads up a number of libraries to handle the parsing.

Comments

0

I wrote this specifically for the purpose of compiling TypeScript in the browser so that I could write quick and simple examples to share.

https://github.com/Sean-Bradley/text-typescript

Usage,

<script type="text/typescript">
    // Your TypeScript code here
</script>

And include dependencies.

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

A complete example you can copy/paste into a HTML doc and try locally.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>"text/typescript" example</title>
        <meta name="description" content="Transpiling and executing TypeScript in the browser" />
        <style>
            body {
                overflow: hidden;
                margin: 0px;
                font-size: 15vw;
            }
        </style>
        <script type="text/typescript">
            function foo(bar: string) {
                return "Hello " + bar;
            }

            let baz = "World!";

            document.getElementById("root").innerHTML = foo(baz);
        </script>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
        <script defer src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
    </head>
    <body>
        <div id="root"></div>
    </body>
</html>

And you can see it working here, right now, today.

https://editor.sbcode.net/f1f4b5a73ec40283d1ddb37bb1e71f7e4e31b487

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.