<h1 dir="auto">JavaScript powered by TypeScript</h1>
<p dir="auto">This proposal outlines the ability to provide a rich JavaScript development experience, by using and extending the capabilities present in TypeScript</p>
<h2 dir="auto">The problem</h2>
<ul dir="auto">
<li>JavaScript intellisense is a mixed bag today. The experiences differ, and it is often inconsistent and/or inaccurate. For example:
<ul dir="auto">
<li>Execution based intellisense falls down on highly dynamic code (e.g. if code depends on external resources or user interaction), behaves differently on different hardware (due to timeout limits in allowing execution), and can be unpredictable (sometimes working or not-working based on seemingly unrelated edits)</li>
<li>Static analysis engines that do in depth code analysis such as tracking call-sites and conditional branches, can often be resource hungry (especially on large code bases) and requires a great deal of code &amp; maintenance to handle the various JavaScript patterns used in the long tail of common libraries &amp; modules</li>
</ul>
</li>
<li>Types are great in TypeScript, and provide for accurate &amp; consistent intellisense, but lots of developers want to keep writing JavaScript directly, or can't address all the TypeScript errors if migrating their existing JavaScript projects. Thus:
<ul dir="auto">
<li>Some of the best JavaScript library definitions are in TypeScript, but are inaccessible to JavaScript developers</li>
<li>Even those wanting to move to projects (or part of them) to TypeScript have a tough challenge converting, due to TypeScript syntax and errors that typically occurs if one just renames a .js file to .ts</li>
</ul>
</li>
<li>Types can be modeled in other ways in JavaScript, such as the common JsDoc comment format, but IDE support and modelling of existing libraries in these other formats is spotty at best</li>
<li>In Visual Studio currently, the integration across JavaScript tooling is poor, resulting in a less than stellar experience if working across areas:
<ul dir="auto">
<li>The JavaScript language service - which is execution based, the Node Tools for Visual Studio - which is analysis based, and the TypeScript tooling - which has a static type system, have limited to zero integration points when authoring code across these project types</li>
<li>Beyond not understanding code across contexts, this results in a disparate editing experience, with ES6 syntax support, auto-formatting, intellisense behavior, etc… all slightly different across the three. (Not to mention the duplicate engineering in writing features and fixing bugs across three implementations)</li>
</ul>
</li>
</ul>
<h2 dir="auto">The opportunity</h2>
<p dir="auto">If the TypeScript language service could be enhanced to work with JavaScript code:</p>
<ul dir="auto">
<li>The extensive library definitions provided by the TypeScript ecosystem could be leveraged, allowing for rich intellisense for common libraries.</li>
<li>Many of the challenges with execution based or analysis engine based intellisense could be avoided (though others occurs, as outlined further below).</li>
<li>As well as JavaScript leveraging the types defined in TypeScript, TypeScript could understand (to a degree) the code in JavaScript files.</li>
<li>This provides an ability to mix TypeScript &amp; JavaScript code within a project, and also gradually migrate code if desired.</li>
<li>The ability of TypeScript to compile ES6+ constructs (classes, arrow functions, modules, etc…) down to ES5 code, could be applied to JavaScript as well (effectively allowing the authoring of ES6 JavaScript to run in ES5 engines). This applies to potentially other features in TypeScript also (e.g. providing JSX support based on TypeScript's TSX support).</li>
<li>Code across (currently) different project types could share context (e.g. browser targeted ES5 JavaScript could understand Node modules written in ES6 JavaScript, and could both leverage interfaces defined in TypeScript).</li>
<li>The editing experience and settings would be consistent across the experiences (and in Visual Studio for example, engineering costs for maintaining three implementations could be spent instead on improving the one).</li>
<li>Being based on the current TypeScript codebase would make this JavaScript experience available outside of Visual Studio (and for very cheap where the TypeScript language service is already used, e.g. the Sublime plugin, the VS Code editor, etc…).</li>
</ul>
<h2 dir="auto">The challenges</h2>
<ul dir="auto">
<li>How to declare and use types within JavaScript (e.g. JsDoc, lib.d.ts, node.d.ts, 3rd party library definitions, custom code, inference, etc…)?</li>
<li>How to support common JavaScript patterns not supported by TypeScript today (RequireJS &amp; CommonJS modules, constructor &amp; prototype properties, etc…)?</li>
<li>How to feed JavaScript into TypeScript compilations (e.g. what files to pick up, compiler options, etc…)?</li>
<li>Assuming the above can be solved, what is the resulting JavaScript developer experience (e.g. making TypeScript "invisible" if just interested in writing JavaScript, the intellisense experience when type inference fails, example project structures and settings for different project types, how to author mixed code or migrate existing code)?</li>
</ul>
<p dir="auto">The above challenges are covered in the following separate write-ups:</p>
<ul dir="auto">
<li><a href="https://github.com/Microsoft/TypeScript/issues/4790" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/4790/hovercard">JavaScript types in TypeScript</a></li>
<li><a href="https://github.com/Microsoft/TypeScript/issues/4791" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/4791/hovercard">JavaScript module systems in TypeScript</a></li>
<li><a href="https://github.com/Microsoft/TypeScript/issues/4792" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/4792/hovercard">JavaScript in TypeScript compilations</a></li>
<li><a href="https://github.com/Microsoft/TypeScript/issues/4793" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/4793/hovercard">JavaScript developer experience</a></li>
</ul>
<p dir="auto"><strong>TypeScript Version:</strong></p>
<p dir="auto">1.9.0-dev (nightly)</p>
<p dir="auto"><strong>Code</strong></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// A self-contained demonstration of the problem follows...
function &lt;T&gt;(arg: T|T[]) {
  if (Array.isArray(arg)) {
    // arg expected to be T[] here, and it has type T[] (works as expected)
  } else {
    // arg expected to be T here, but it is has type T|T[] (unexpected behaviour)
  }
}"><pre class="notranslate"><span class="pl-c">// A self-contained demonstration of the problem follows...</span>
<span class="pl-k">function</span> <span class="pl-c1">&lt;</span><span class="pl-smi">T</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">arg</span>: <span class="pl-smi">T</span><span class="pl-c1">|</span><span class="pl-smi">T</span><span class="pl-kos">[</span><span class="pl-kos">]</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">Array</span><span class="pl-kos">.</span><span class="pl-en">isArray</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// arg expected to be T[] here, and it has type T[] (works as expected)</span>
  <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
    <span class="pl-c">// arg expected to be T here, but it is has type T|T[] (unexpected behaviour)</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>