<p dir="auto">The idea is to instrument JavaScript code and collect types information from the runtime. For example:</p>
<p dir="auto">Consider JavaScript code (in ES2015):</p>
<p dir="auto">File <code class="notranslate">render.js</code>:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export function renderContact(contact, container) {
  let span = document.createElement('span');
  span.textContent = `${contact.firstName} ${contact.secondName}`;
  container.appendChild(span);
}"><pre class="notranslate"><span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-en">renderContact</span><span class="pl-kos">(</span><span class="pl-s1">contact</span><span class="pl-kos">,</span> <span class="pl-s1">container</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">let</span> <span class="pl-s1">span</span> <span class="pl-c1">=</span> <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'span'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-s1">span</span><span class="pl-kos">.</span><span class="pl-c1">textContent</span> <span class="pl-c1">=</span> <span class="pl-s">`<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">contact</span><span class="pl-kos">.</span><span class="pl-c1">firstName</span><span class="pl-kos">}</span></span> <span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">contact</span><span class="pl-kos">.</span><span class="pl-c1">secondName</span><span class="pl-kos">}</span></span>`</span><span class="pl-kos">;</span>
  <span class="pl-s1">container</span><span class="pl-kos">.</span><span class="pl-en">appendChild</span><span class="pl-kos">(</span><span class="pl-s1">span</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Then we use it in file <code class="notranslate">main.js</code>:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import {renderContact} from &quot;./render&quot;;

renderContact({firstName: &quot;Steve&quot;, lastName: &quot;Works&quot;}, document.body);"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-kos">{</span><span class="pl-s1">renderContact</span><span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">"./render"</span><span class="pl-kos">;</span>

<span class="pl-en">renderContact</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-c1">firstName</span>: <span class="pl-s">"Steve"</span><span class="pl-kos">,</span> <span class="pl-c1">lastName</span>: <span class="pl-s">"Works"</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-c1">body</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Running this code as-is gives no help, but if it's instrumented then we may callect runtime information. <code class="notranslate">main.js</code> could be instrumented to the following form using esprima/escodegen or TypeScript's parser API:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import {renderContact} from &quot;./render&quot;;

CallExpression({line:3, col:0},
               null, 
               renderContact, 
               [{firstName: &quot;Steve&quot;, lastName: &quot;Works&quot;}, document.body]) "><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-kos">{</span><span class="pl-s1">renderContact</span><span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">"./render"</span><span class="pl-kos">;</span>

<span class="pl-v">CallExpression</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-c1">line</span>:<span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">col</span>:<span class="pl-c1">0</span><span class="pl-kos">}</span><span class="pl-kos">,</span>
               <span class="pl-c1">null</span><span class="pl-kos">,</span> 
               <span class="pl-s1">renderContact</span><span class="pl-kos">,</span> 
               <span class="pl-kos">[</span><span class="pl-kos">{</span><span class="pl-c1">firstName</span>: <span class="pl-s">"Steve"</span><span class="pl-kos">,</span> <span class="pl-c1">lastName</span>: <span class="pl-s">"Works"</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-c1">body</span><span class="pl-kos">]</span><span class="pl-kos">)</span> </pre></div>
<p dir="auto"><code class="notranslate">CallExpression</code> body could roughly look like:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function CallExpression(position:Position, callee:any, fn:Function, args:any[) {
    // collect types information part
    args.forEach(arg=&gt;CollectArgumentTypesInformation(position, arg));

    // execution part to conform JavaScript semantics and do not break the running application code
    return fn.apply(callee, args);   
}


function CollectArgumentTypesInformation(position:Position, arg:any) {
    let type={};
    Object.keys(arg).forEach(key=&gt;{
        type[key]=typeof arg[key];
    });   
    return type;
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-smi">CallExpression</span><span class="pl-kos">(</span><span class="pl-s1">position</span>:<span class="pl-smi">Position</span><span class="pl-kos">,</span> <span class="pl-s1">callee</span>:<span class="pl-smi">any</span><span class="pl-kos">,</span> <span class="pl-s1">fn</span>:<span class="pl-smi">Function</span><span class="pl-kos">,</span> <span class="pl-s1">args</span>:<span class="pl-smi">any</span><span class="pl-kos">[</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// collect types information part</span>
    <span class="pl-s1">args</span><span class="pl-kos">.</span><span class="pl-en">forEach</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-c1">=&gt;</span><span class="pl-smi">CollectArgumentTypesInformation</span><span class="pl-kos">(</span><span class="pl-s1">position</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">// execution part to conform JavaScript semantics and do not break the running application code</span>
    <span class="pl-k">return</span> <span class="pl-s1">fn</span><span class="pl-kos">.</span><span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-s1">callee</span><span class="pl-kos">,</span> <span class="pl-s1">args</span><span class="pl-kos">)</span><span class="pl-kos">;</span>   
<span class="pl-kos">}</span>


<span class="pl-k">function</span> <span class="pl-smi">CollectArgumentTypesInformation</span><span class="pl-kos">(</span><span class="pl-s1">position</span>:<span class="pl-smi">Position</span><span class="pl-kos">,</span> <span class="pl-s1">arg</span>:<span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-s1">type</span><span class="pl-c1">=</span><span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
    <span class="pl-smi">Object</span><span class="pl-kos">.</span><span class="pl-en">keys</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-en">forEach</span><span class="pl-kos">(</span><span class="pl-s1">key</span><span class="pl-c1">=&gt;</span><span class="pl-kos">{</span>
        <span class="pl-s1">type</span><span class="pl-kos">[</span><span class="pl-s1">key</span><span class="pl-kos">]</span><span class="pl-c1">=</span><span class="pl-k">typeof</span> <span class="pl-s1">arg</span><span class="pl-kos">[</span><span class="pl-s1">key</span><span class="pl-kos">]</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">return</span> <span class="pl-s1">type</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><code class="notranslate">CollectArgumentTypesInformation</code> for <code class="notranslate">contact</code> parameter would yield something like:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="{
    firstName:string,
    lastName:string
}"><pre class="notranslate"><span class="pl-kos">{</span>
    <span class="pl-c1">firstName</span>:<span class="pl-s1">string</span><span class="pl-kos">,</span>
    <span class="pl-c1">lastName</span>:<span class="pl-s1">string</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">that could be later transformed into interface <code class="notranslate">contact</code> (name of the interface is based on <code class="notranslate">renderContact</code> 1st parameter name):</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface contact {
    firstName:string,
    lastName:string
}"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-smi">contact</span> <span class="pl-kos">{</span>
    <span class="pl-c1">firstName</span>:<span class="pl-smi">string</span><span class="pl-kos">,</span>
    <span class="pl-c1">lastName</span>:<span class="pl-smi">string</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Later on this TypeScript type could be injected into the file like <code class="notranslate">render.ts</code> (next to the <code class="notranslate">render.js</code>) and then be used to generate <code class="notranslate">d.ts</code> file using TypeScript's <code class="notranslate">tsc --declaration</code>. Before running <code class="notranslate">tsc --declaration</code> author could refactor names for better naming and the instrumentation and types collection tool would respect that changes and wouldn't override them.</p>
<p dir="auto"><code class="notranslate">position</code> would be used to source-map <code class="notranslate">.js</code> and <code class="notranslate">.ts</code> files. Or it could be something similar, maybe using <code class="notranslate">sourceMaps</code> project itself.</p>
<p dir="auto">From <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="141163009" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/7535" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/7535/hovercard" href="https://github.com/microsoft/TypeScript/issues/7535">#7535</a>, it would be useful for JavaScript package authors to have the ability to generate declarations from their project. This would help with getting started on a type definition (it would be populated with known interfaces/functions/types that are exported) and would also allow the creation of continuous integration scripts that check the JavaScript types with the hand-coded definition for inconsistencies.</p>