es7 proposal : https://github.com/sebmarkbage/ecmascript-rest-spread ## Spread properties ### Typing 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 : ``` typescript var obj = { x: 1, y: 2}; var obj1 = {...obj, z: 3, y: 4}; // not an error ``` I have a very naive [type check algorithm](https://github.com/fdecampredon/jsx-typescript/blob/3c692cbb80622b74d1b308b3c5dcab6b993b4111/src/compiler/checker.ts#L5665-L5671) for a similar feature (`JSXSpreadAttribute`) in my little `jsx-typescript` fork: I just copy the properties of the _spread object_ in the properties table when I encounter a spread object, and override those property if I encounter a declaration with a similar name. ### Emitting [jstransform](https://github.com/facebook/jstransform/) use `Object.assign`, [babel](https://babeljs.io/) introduce a shim: ``` javascript var _extends = Object.assign || function (target) { for (var i = 1; i < 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; }; ``` We could either force the presence of `assign` function on `ObjectConstructor` interface, or provide a similar function (with a different name). I think that the optimal solution would be to not emit any helper in `es6` target (or if `Object.assign` is defined), and to emit an helper function for `es5`, `es3`. ``` javascript 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 < 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 }); ``` ## Rest properties ### Typing 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 : ``` typescript var obj = {x:1, y: 1, z: 1}; var {z, ...obj1} = obj; obj1// {x: number; y:number}; ``` If the destructuring assignment has an index declaration, the result has also a similar index declaration: ``` typescript var obj: { [string: string]: string }; var {[excludedId], ...obj1} = obj; obj1// { [string: string]: string }; ``` new/call declarations are obviously not captured: ``` typescript var obj: { (): void; property: string}; var { ...obj1} = obj; obj1// { property: string }; ``` ### Emitting It is not possible to emit _rest properties_ without an helper function, this one is from babel: ``` typescript var obj = {x:1, y: 1, z: 1}; var {z, ...obj1} = obj; ``` ``` javascript var __objectWithoutProperties = function(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 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, ["z"]); ``` _Edit: added some little typing/emitting example_