ブラウザでTypeScript実行のサンプル

デモ1: script要素に直書きのTypeScript

TypeScript realtime transpile and execution demo.

[Status] Processing...

[Loaded Data]

コード

script要素指定


<script async type="module">
  // TypeScript本家のパッケージ
  import { transpile, ScriptTarget } from 'https://esm.sh/typescript@5.3.3?bundle&target=esnext';
  // ソースコード圧縮し、minifyするパッケージ
  import { minify_sync } from 'https://esm.sh/terser@5.27.0?bundle&target=esnext';

  // script 要素のうち、メディアタイプがTypeScriptな要素のみを抽出しJavaScriptにトランスパイルする
  for (const {type, textContent} of document.getElementsByTagName('script')) {
      if(type !== 'text/typescript' || !textContent){
          continue;
      }

      // TypeScriptからJavaScriptへのトラインスパイルを実行
      const js = transpile(textContent, {
          target: ScriptTarget.ESNext
      });

      // ソースコードの圧縮
      const { code } = minify_sync(js, {
          module: true
      });

      // UTF-8でエンコードしBASE64へ変換したDataURLへ変換
      // 動的インポートでJavaScriptを読み込んで実行
      await import(`data:text/javascript;charset=utf-8,${encodeURIComponent(code)}`);
  }
</script>

<script type="text/typescript">
    interface Demo {
        a: string;
        b: number;
        c: boolean;
    }
    const demo: Demo = {
        a: 'aaa',
        b: 111,
        c: true,
    };

    // 擬似的に通信時の遅延状態を再現
    await new Promise(done => setTimeout(done, 100));
    console.log('デモ1: ', demo);

    // 結果を画面に表示
    const statusElement = document.getElementById('status1');
    const dataElement = document.getElementById('data1');
    statusElement.textContent = 'Complete!';
    dataElement.textContent = JSON.stringify(demo);

    // コードのシンタックスハイライト
    hljs.highlightElement(dataElement)
</script>
            

HTML


<p>[Status] <i id="status1">Processing...</i></p>
<p>[Loaded Data]
  <pre><code id="data1" class="language-json"></code></pre>
</p>
            

デモ2: TypeScriptファイルの読み込み

TypeScript file realtime transpile and execution demo.

[Status] Processing...

[Loaded Data]

コード

./demo.ts


interface Demo {
  e: string;
  f: number;
  g: boolean;
}

const demo: Demo = {
  e: 'eee',
  f: 222,
  g: false,
};

export function execute(statusElement: HTMLElement, dataElement: HTMLElement): Promise<Demo> {
  return new Promise(async (resolve, reject) => {
    // 擬似的に通信時の遅延状態を再現
    await new Promise(done => setTimeout(done, 100));

    // 結果を画面に表示
    statusElement.textContent = 'Complete!';
    dataElement.textContent = JSON.stringify(demo);

    resolve(demo);
  });
}
            

./ts-transpile.js


// TypeScript本家のパッケージ
import { transpile, ScriptTarget } from 'https://esm.sh/typescript@5.3.3?bundle&target=esnext';
// ソースコード圧縮し、minifyするパッケージ
import { minify_sync } from 'https://esm.sh/terser@5.27.0?bundle&target=esnext';

/**
  * TypeScriptファイルを読み込み、JavaScriptにトランスパイルして圧縮したDataURLを返す
  * @param {string} url TypeScriptファイルのURL
  * @returns {Promise}
  */
export async function transpileTS(url) {
  const response = await fetch(url);
  const tsText = await response.text();

  // TypeScriptからJavaScriptへのトラインスパイルを実行
  const js = transpile(tsText, {
    target: ScriptTarget.ESNext,
  });

  // ソースコードの圧縮
  const { code } = minify_sync(js, {
    module: true,
  });

  // UTF-8でエンコードしBASE64へ変換したDataURLへ変換
  return `data:text/javascript;charset=utf-8,${encodeURIComponent(code)}`;
}
            

script要素指定


<script async type="module">
  // TypeScriptからJavaScriptへ変換するためのJSを読み込み
  import { transpileTS } from './ts-transpile.js';

  // TypeScriptファイルの読み込んで、DataURL形式のJavaScriptに変換
  const dataUrlJs = await transpileTS('./demo.ts');
  // 変換したJavaScriptを読み込み
  const demo = await import(dataUrlJs);

  // 読み込んだスクリプトの実行
  const statusElement = document.getElementById('status2');
  const dataElement = document.getElementById('data2');
  const values = await demo.execute(statusElement, dataElement);
  console.log('デモ2: ', values);

  // コードのシンタックスハイライト
  hljs.highlightElement(dataElement)
</script>
            

HTML


<p>[Status] <i id="status2">Processing...</i></p>
<p>[Loaded Data]
  <pre><code id="data2" class="language-json"></code></pre>
</p>