<p dir="auto">Object Spread Initializers is a proposed feature of ES2016 and is very useful when writing Redux reducers. The syntax is supported in babel, but when using the feature in Visual Studio Code it will mark the spread operator as a syntax error.</p>
<p dir="auto">See: <a href="https://github.com/sebmarkbage/ecmascript-rest-spread/blob/master/Spread.md">https://github.com/sebmarkbage/ecmascript-rest-spread/blob/master/Spread.md</a><br>
for more information of the feature.</p>
<p dir="auto">It would be very nice if Visual Studio Code did not mark the use of this feature as an error with a red squiggly.</p>
<p dir="auto">The current behavior in Visual Studio Code is also described in Issue <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="123821951" data-permission-text="Title is private" data-url="https://github.com/microsoft/vscode/issues/1640" data-hovercard-type="issue" data-hovercard-url="/microsoft/vscode/issues/1640/hovercard" href="https://github.com/microsoft/vscode/issues/1640">#1640</a></p>
<p dir="auto">es7 proposal : <a href="https://github.com/sebmarkbage/ecmascript-rest-spread">https://github.com/sebmarkbage/ecmascript-rest-spread</a></p>
<h2 dir="auto">Spread properties</h2>
<h3 dir="auto">Typing</h3>
<p dir="auto">In my opinion the goal of this method is to be able to duplicate an object and changing some props, so I think it's particularly important in this case to not check duplicate property declaration :</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var obj = { x: 1, y: 2};
var obj1 = {...obj, z: 3, y: 4}; // not an error"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">obj</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span> <span class="pl-c1">x</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">y</span>: <span class="pl-c1">2</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">obj1</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>...<span class="pl-s1">obj</span><span class="pl-kos">,</span> <span class="pl-c1">z</span>: <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">y</span>: <span class="pl-c1">4</span><span class="pl-kos">}</span><span class="pl-kos">;</span> <span class="pl-c">// not an error</span></pre></div>
<p dir="auto">I have a very naive <a href="https://github.com/fdecampredon/jsx-typescript/blob/3c692cbb80622b74d1b308b3c5dcab6b993b4111/src/compiler/checker.ts#L5665-L5671">type check algorithm</a> for a similar feature (<code class="notranslate">JSXSpreadAttribute</code>) in my little <code class="notranslate">jsx-typescript</code> fork: I just copy the properties of the <em>spread object</em> in the properties table when I encounter a spread object, and override those property if I encounter a declaration with a similar name.</p>
<h3 dir="auto">Emitting</h3>
<p dir="auto"><a href="https://github.com/facebook/jstransform/">jstransform</a> use <code class="notranslate">Object.assign</code>, <a href="https://babeljs.io/" rel="nofollow">babel</a> introduce a shim:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var _extends = Object.assign || function (target) { for (var i = 1; i &lt; arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">_extends</span> <span class="pl-c1">=</span> <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-c1">assign</span> <span class="pl-c1">||</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">target</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">var</span> <span class="pl-s1">i</span> <span class="pl-c1">=</span> <span class="pl-c1">1</span><span class="pl-kos">;</span> <span class="pl-s1">i</span> <span class="pl-c1">&lt;</span> <span class="pl-smi">arguments</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">;</span> <span class="pl-s1">i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-k">var</span> <span class="pl-s1">source</span> <span class="pl-c1">=</span> <span class="pl-smi">arguments</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">;</span> <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">var</span> <span class="pl-s1">key</span> <span class="pl-k">in</span> <span class="pl-s1">source</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-v">Object</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span><span class="pl-kos">.</span><span class="pl-c1">hasOwnProperty</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-s1">source</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-s1">target</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-s1">source</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">target</span><span class="pl-kos">;</span> <span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">We could either force the presence of <code class="notranslate">assign</code> function on <code class="notranslate">ObjectConstructor</code> interface, or provide a similar function (with a different name).</p>
<p dir="auto">I think that the optimal solution would be to not emit any helper in <code class="notranslate">es6</code> target (or if <code class="notranslate">Object.assign</code> is defined), and to emit an helper function for <code class="notranslate">es5</code>, <code class="notranslate">es3</code>.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var obj = { x: 1, y: 2};
var obj1 = {...obj, z: 3};

/// ES6 emit
var obj = {x: 1, y: 2};
var obj1= Object.assign({}, obj, { z: 3 });

//ES3 emit
var __assign = function (target) { 
    for (var i = 1; i &lt; arguments.length; i++) { 
        var source = arguments[i]; 
        for (var key in source) { 
            if (Object.prototype.hasOwnProperty.call(source, key)) { 
                target[key] = source[key];
            } 
        } 
    } 
    return target; 
};

var obj = {x: 1, y: 2};
var obj1= __assign({}, obj, { z: 3 });"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">obj</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span> <span class="pl-c1">x</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">y</span>: <span class="pl-c1">2</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">obj1</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>...<span class="pl-s1">obj</span><span class="pl-kos">,</span> <span class="pl-c1">z</span>: <span class="pl-c1">3</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-c">/// ES6 emit</span>
<span class="pl-k">var</span> <span class="pl-s1">obj</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-c1">x</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">y</span>: <span class="pl-c1">2</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">obj1</span><span class="pl-c1">=</span> <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-en">assign</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s1">obj</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">z</span>: <span class="pl-c1">3</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">//ES3 emit</span>
<span class="pl-k">var</span> <span class="pl-en">__assign</span> <span class="pl-c1">=</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">target</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> 
    <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">var</span> <span class="pl-s1">i</span> <span class="pl-c1">=</span> <span class="pl-c1">1</span><span class="pl-kos">;</span> <span class="pl-s1">i</span> <span class="pl-c1">&lt;</span> <span class="pl-smi">arguments</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">;</span> <span class="pl-s1">i</span><span class="pl-c1">++</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> 
        <span class="pl-k">var</span> <span class="pl-s1">source</span> <span class="pl-c1">=</span> <span class="pl-smi">arguments</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span><span class="pl-kos">;</span> 
        <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">var</span> <span class="pl-s1">key</span> <span class="pl-k">in</span> <span class="pl-s1">source</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-v">Object</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span><span class="pl-kos">.</span><span class="pl-c1">hasOwnProperty</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-s1">source</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-s1">target</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-s1">source</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">target</span><span class="pl-kos">;</span> 
<span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">var</span> <span class="pl-s1">obj</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-c1">x</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">y</span>: <span class="pl-c1">2</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">obj1</span><span class="pl-c1">=</span> <span class="pl-en">__assign</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s1">obj</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">z</span>: <span class="pl-c1">3</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<h2 dir="auto">Rest properties</h2>
<h3 dir="auto">Typing</h3>
<p dir="auto">For simple object the new type is a subtype of the assignation that does not contains properties that has been captured before the rest properties :</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var obj = {x:1, y: 1, z: 1};
var {z, ...obj1} = obj;
obj1// {x: number; y:number};"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">obj</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-c1">x</span>:<span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">y</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">z</span>: <span class="pl-c1">1</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-kos">{</span>z<span class="pl-kos">,</span> ...<span class="pl-s1">obj1</span><span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-s1">obj</span><span class="pl-kos">;</span>
<span class="pl-s1">obj1</span><span class="pl-c">// {x: number; y:number};</span></pre></div>
<p dir="auto">If the destructuring assignment has an index declaration, the result has also a similar index declaration:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var obj: { [string: string]: string };
var {[excludedId], ...obj1} = obj;
obj1// { [string: string]: string };"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">obj</span>: <span class="pl-kos">{</span> <span class="pl-kos">[</span><span class="pl-s1">string</span>: <span class="pl-smi">string</span><span class="pl-kos">]</span>: <span class="pl-smi">string</span> <span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-kos">{</span><span class="pl-kos">[</span><span class="pl-s1">excludedId</span><span class="pl-kos">]</span><span class="pl-kos">,</span> ...<span class="pl-s1">obj1</span><span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-s1">obj</span><span class="pl-kos">;</span>
<span class="pl-s1">obj1</span><span class="pl-c">// { [string: string]: string };</span></pre></div>
<p dir="auto">new/call declarations are obviously not captured:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var obj: { (): void; property: string};
var { ...obj1} = obj;
obj1// { property: string };"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">obj</span>: <span class="pl-kos">{</span> <span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">;</span> <span class="pl-c1">property</span>: <span class="pl-smi">string</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-kos">{</span> ...<span class="pl-s1">obj1</span><span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-s1">obj</span><span class="pl-kos">;</span>
<span class="pl-s1">obj1</span><span class="pl-c">// { property: string };</span></pre></div>
<h3 dir="auto">Emitting</h3>
<p dir="auto">It is not possible to emit <em>rest properties</em> without an helper function, this one is from babel:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var obj = {x:1, y: 1, z: 1};
var {z, ...obj1} = obj;"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">obj</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-c1">x</span>:<span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">y</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">z</span>: <span class="pl-c1">1</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-kos">{</span>z<span class="pl-kos">,</span> ...<span class="pl-s1">obj1</span><span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-s1">obj</span><span class="pl-kos">;</span></pre></div>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var __objectWithoutProperties = function(obj, keys) {
    var target = {};
    for (var i in obj) {
        if (keys.indexOf(i) &gt;= 0) continue;
        if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
        target[i] = obj[i];
    }
    return target;
};

var obj = {x:1, y: 1, z: 1};
var z = obj.z;
var obj1 = __objectWithoutProperties(obj, [&quot;z&quot;]);"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-en">__objectWithoutProperties</span> <span class="pl-c1">=</span> <span class="pl-k">function</span><span class="pl-kos">(</span><span class="pl-s1">obj</span><span class="pl-kos">,</span> <span class="pl-s1">keys</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">var</span> <span class="pl-s1">target</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
    <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">var</span> <span class="pl-s1">i</span> <span class="pl-k">in</span> <span class="pl-s1">obj</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-s1">keys</span><span class="pl-kos">.</span><span class="pl-en">indexOf</span><span class="pl-kos">(</span><span class="pl-s1">i</span><span class="pl-kos">)</span> <span class="pl-c1">&gt;=</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-k">continue</span><span class="pl-kos">;</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">!</span><span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-c1">prototype</span><span class="pl-kos">.</span><span class="pl-c1">hasOwnProperty</span><span class="pl-kos">.</span><span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-s1">obj</span><span class="pl-kos">,</span> <span class="pl-s1">i</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-k">continue</span><span class="pl-kos">;</span>
        <span class="pl-s1">target</span><span class="pl-kos">[</span><span class="pl-s1">i</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-s1">obj</span><span class="pl-kos">[</span><span class="pl-s1">i</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">target</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">var</span> <span class="pl-s1">obj</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-c1">x</span>:<span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">y</span>: <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">z</span>: <span class="pl-c1">1</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">z</span> <span class="pl-c1">=</span> <span class="pl-s1">obj</span><span class="pl-kos">.</span><span class="pl-c1">z</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">obj1</span> <span class="pl-c1">=</span> <span class="pl-en">__objectWithoutProperties</span><span class="pl-kos">(</span><span class="pl-s1">obj</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-s">"z"</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><em>Edit: added some little typing/emitting example</em></p>