Support proposed ES Rest/Spread properties #2103

Closed
fdecampredon opened this Issue Feb 21, 2015 · 96 comments

Comments

Projects
None yet
@fdecampredon

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 :

var obj = { x: 1, y: 2};
var obj1 = {...obj, z: 3, y: 4}; // not an error

I have a very naive type check algorithm 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 use Object.assign, babel introduce a shim:

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.

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 :

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:

var obj: { [string: string]: string };
var {[excludedId], ...obj1} = obj;
obj1// { [string: string]: string };

new/call declarations are obviously not captured:

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:

var obj = {x:1, y: 1, z: 1};
var {z, ...obj1} = obj;
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

@RyanCavanaugh

This comment has been minimized.

Show comment
Hide comment
@RyanCavanaugh

RyanCavanaugh Feb 23, 2015

Member

We'd probably need some examples of how this could plausibly be emitted in downlevel (if that's in scope).

Member

RyanCavanaugh commented Feb 23, 2015

We'd probably need some examples of how this could plausibly be emitted in downlevel (if that's in scope).

@fdecampredon

This comment has been minimized.

Show comment
Hide comment
@fdecampredon

fdecampredon Feb 23, 2015

@RyanCavanaugh, I added some little emitting example and typing idea.
I would like to work on that one since anyway it's more or less a jsx feature and I will need to add it to my fork, but if it's added to typescript core it's better ^^.

@RyanCavanaugh, I added some little emitting example and typing idea.
I would like to work on that one since anyway it's more or less a jsx feature and I will need to add it to my fork, but if it's added to typescript core it's better ^^.

@mnpenner

This comment has been minimized.

Show comment
Hide comment
@mnpenner

mnpenner Jul 10, 2015

I recently discovered this feature in ES7 via this article. I have to say, it's quite handy!

Would love to see this in TypeScript!

I recently discovered this feature in ES7 via this article. I have to say, it's quite handy!

Would love to see this in TypeScript!

@prabirshrestha

This comment has been minimized.

Show comment
Hide comment
@prabirshrestha

prabirshrestha Jul 11, 2015

Member

Any updates on this? Would love to see this in 1.6 as it would come super handy when using with React 😄

Member

prabirshrestha commented Jul 11, 2015

Any updates on this? Would love to see this in 1.6 as it would come super handy when using with React 😄

@DanielRosenwasser

This comment has been minimized.

Show comment
Hide comment
@DanielRosenwasser

DanielRosenwasser Jul 11, 2015

Member

@prabirshrestha for the record, we currently have the property spread operator for JSX on master.

Member

DanielRosenwasser commented Jul 11, 2015

@prabirshrestha for the record, we currently have the property spread operator for JSX on master.

@mnpenner

This comment has been minimized.

Show comment
Hide comment
@mnpenner

mnpenner Jul 11, 2015

@DanielRosenwasser Could you elaborate? Does that mean this works on master with the --jsx flag? Does that include rest properties or just spread properties?

@DanielRosenwasser Could you elaborate? Does that mean this works on master with the --jsx flag? Does that include rest properties or just spread properties?

@DanielRosenwasser

This comment has been minimized.

Show comment
Hide comment
@DanielRosenwasser

DanielRosenwasser Jul 11, 2015

Member

Sorry @mnpenner and @prabirshrestha, yes, I meant on master. @RyanCavanaugh knows more about this than I do, but I believe it's just spread properties.

Member

DanielRosenwasser commented Jul 11, 2015

Sorry @mnpenner and @prabirshrestha, yes, I meant on master. @RyanCavanaugh knows more about this than I do, but I believe it's just spread properties.

@RyanCavanaugh

This comment has been minimized.

Show comment
Hide comment
@RyanCavanaugh

RyanCavanaugh Jul 13, 2015

Member

JSX supports spread attributes, e.g. <TagName {...spreadedExpr} />. Nothing to do with the ES6 spread operator other than sharing the same token and having roughly equivalent semantics.

Member

RyanCavanaugh commented Jul 13, 2015

JSX supports spread attributes, e.g. <TagName {...spreadedExpr} />. Nothing to do with the ES6 spread operator other than sharing the same token and having roughly equivalent semantics.

@RichiCoder1

This comment has been minimized.

Show comment
Hide comment
@RichiCoder1

RichiCoder1 Aug 7, 2015

I'm very interested in both Redux and React, the manipulation in state is made much easier with this. Would love to see this implemented.

I'm very interested in both Redux and React, the manipulation in state is made much easier with this. Would love to see this implemented.

@Lenne231

This comment has been minimized.

Show comment
Hide comment
@RyanCavanaugh

This comment has been minimized.

Show comment
Hide comment
@RyanCavanaugh

RyanCavanaugh Oct 5, 2015

Member

We want to wait for the proposal to reach Stage 3 before addressing this.

Member

RyanCavanaugh commented Oct 5, 2015

We want to wait for the proposal to reach Stage 3 before addressing this.

@WanderWang

This comment has been minimized.

Show comment
Hide comment
@WanderWang

WanderWang Nov 6, 2015

It's very useful in react and redux , please implement it as soon as possible , please :-)

It's very useful in react and redux , please implement it as soon as possible , please :-)

@tomduncalf

This comment has been minimized.

Show comment
Hide comment
@tomduncalf

tomduncalf Nov 13, 2015

Here's a helper module I've been using to work around this. It's not ideal as you have to specify all the keys twice, once on the left hand side and once as strings on the right hand side, but I can't think of a better way to do it. Any feedback welcome, I'm sure there's edge behaviour I've missed!

https://gist.github.com/tomduncalf/fbae862b123445c117cb

Here's a helper module I've been using to work around this. It's not ideal as you have to specify all the keys twice, once on the left hand side and once as strings on the right hand side, but I can't think of a better way to do it. Any feedback welcome, I'm sure there's edge behaviour I've missed!

https://gist.github.com/tomduncalf/fbae862b123445c117cb

@nevir

This comment has been minimized.

Show comment
Hide comment
@nevir

nevir Nov 18, 2015

Is this something you'd accept a patch for? (to be merged once it reaches stage 3). And if so, have any pointers of where to start making changes to support it?

This is the last ES7+ feature that my team heavily uses that's preventing us from switching over to typescript; would definitely love to have to sooner, if possible.

nevir commented Nov 18, 2015

Is this something you'd accept a patch for? (to be merged once it reaches stage 3). And if so, have any pointers of where to start making changes to support it?

This is the last ES7+ feature that my team heavily uses that's preventing us from switching over to typescript; would definitely love to have to sooner, if possible.

@mhegazy

This comment has been minimized.

Show comment
Hide comment
@mhegazy

mhegazy Nov 19, 2015

Contributor

We would consider a PR here. One note though, wiring the type system for this feature is not a simple task. If you are interested in perusing this I would keep it incremental, and would start by parsing then emit then type checking. @sandersn should be able to help you if you have any questions.

Contributor

mhegazy commented Nov 19, 2015

We would consider a PR here. One note though, wiring the type system for this feature is not a simple task. If you are interested in perusing this I would keep it incremental, and would start by parsing then emit then type checking. @sandersn should be able to help you if you have any questions.

@xogeny

This comment has been minimized.

Show comment
Hide comment
@xogeny

xogeny Dec 4, 2015

Just a note for those interested in using this with Redux. I agree the notation is convenient. But I've actually been getting by just fine without it by leverage the updeep library. I created some basic typings for it and it works pretty well. I even have a simple library that implements an updeep based store and actions. If anybody is interested in this, just contact me.

In any case, 👍 for spread operators in TS. 😄

xogeny commented Dec 4, 2015

Just a note for those interested in using this with Redux. I agree the notation is convenient. But I've actually been getting by just fine without it by leverage the updeep library. I created some basic typings for it and it works pretty well. I even have a simple library that implements an updeep based store and actions. If anybody is interested in this, just contact me.

In any case, 👍 for spread operators in TS. 😄

@cur3n4

This comment has been minimized.

Show comment
Hide comment
@cur3n4

cur3n4 Dec 13, 2015

@xogeny I would be very interested in having a look at that library. Thanks

cur3n4 commented Dec 13, 2015

@xogeny I would be very interested in having a look at that library. Thanks

@xogeny

This comment has been minimized.

Show comment
Hide comment
@xogeny

xogeny Dec 13, 2015

@cur3n4 I have a repository where I've been playing with these ideas. It changes quite a bit (since this is all still evolving). I was using a special modules that leveraged updeep initially and that functionality is still in the library. But I've stopped using it because I found it difficult to maintain the necessary type constraints. I suspect if Typescript had something along the lines of Java's super generic type constraints, updeep (and several other libraries, like lodash or ramda) could be made a lot more type safe.

But don't get me wrong, I still think a spread operator would be really useful. It would actually allow you to express and do things safely and tersely in the language that I don't see how to do with the current type system (i.e., allowing you to describe the right type constraints on external libraries). For the moment, I sacrifice the terseness for the safety (while the updeep approach sacrificed safety for terseness).

xogeny commented Dec 13, 2015

@cur3n4 I have a repository where I've been playing with these ideas. It changes quite a bit (since this is all still evolving). I was using a special modules that leveraged updeep initially and that functionality is still in the library. But I've stopped using it because I found it difficult to maintain the necessary type constraints. I suspect if Typescript had something along the lines of Java's super generic type constraints, updeep (and several other libraries, like lodash or ramda) could be made a lot more type safe.

But don't get me wrong, I still think a spread operator would be really useful. It would actually allow you to express and do things safely and tersely in the language that I don't see how to do with the current type system (i.e., allowing you to describe the right type constraints on external libraries). For the moment, I sacrifice the terseness for the safety (while the updeep approach sacrificed safety for terseness).

@amcdnl

This comment has been minimized.

Show comment
Hide comment
@amcdnl

amcdnl Jan 26, 2016

After using Babel for past few months, converted my project to TS and had to go and redo all these. Would love to see this implemented!

amcdnl commented Jan 26, 2016

After using Babel for past few months, converted my project to TS and had to go and redo all these. Would love to see this implemented!

@SergeyKorochansky

This comment has been minimized.

Show comment
Hide comment
@dlebedynskyi

This comment has been minimized.

Show comment
Hide comment
@dlebedynskyi

dlebedynskyi Jan 28, 2016

would love to see this.

would love to see this.

@danielfigueiredo

This comment has been minimized.

Show comment
Hide comment
@mezzario

This comment has been minimized.

Show comment
Hide comment
@mezzario

mezzario Jan 28, 2016

must have feature, please implement

must have feature, please implement

@lukephills

This comment has been minimized.

Show comment
Hide comment

+1

@mhegazy mhegazy changed the title from Support es7 Rest/Spread properties to Support ES8 Rest/Spread properties Feb 4, 2016

@mhegazy mhegazy added ES Next and removed ES7 labels Feb 4, 2016

@mhegazy mhegazy changed the title from Support ES8 Rest/Spread properties to Support proposed ES Rest/Spread properties Feb 4, 2016

@baio

This comment has been minimized.

Show comment
Hide comment
@baio

baio Feb 6, 2016

+1 much nicer syntax than Object.assign + JSX support

baio commented Feb 6, 2016

+1 much nicer syntax than Object.assign + JSX support

@ddaghan

This comment has been minimized.

Show comment
Hide comment
@ddaghan

ddaghan Sep 22, 2016

Since mostly people here want to use this with react, why not implement this just for *.tsx files until it reaches stage 3?

Redux reducers can be written as *.tsx files too, just obj typecasting instances should be converted to obj as Type

ddaghan commented Sep 22, 2016

Since mostly people here want to use this with react, why not implement this just for *.tsx files until it reaches stage 3?

Redux reducers can be written as *.tsx files too, just obj typecasting instances should be converted to obj as Type

@olegman

This comment has been minimized.

Show comment
Hide comment
@olegman

olegman Sep 22, 2016

This very useful not only for react, but in redux reducers for example.

olegman commented Sep 22, 2016

This very useful not only for react, but in redux reducers for example.

@kitsonk

This comment has been minimized.

Show comment
Hide comment
@kitsonk

kitsonk Sep 22, 2016

Contributor

I think the tags and missing milestone on this are a bit out of date. Because this is committed and being worked on (#10727) for TypeScript 2.1. So no need to debate the value of it anymore.

ping @mhegazy

Contributor

kitsonk commented Sep 22, 2016

I think the tags and missing milestone on this are a bit out of date. Because this is committed and being worked on (#10727) for TypeScript 2.1. So no need to debate the value of it anymore.

ping @mhegazy

@mhegazy mhegazy added Committed and removed In Discussion labels Sep 22, 2016

@mhegazy mhegazy added this to the TypeScript 2.1 milestone Sep 22, 2016

@mhegazy

This comment has been minimized.

Show comment
Hide comment
@mhegazy

mhegazy Sep 22, 2016

Contributor

Updated the tags. I should clarify that the reason this has not been implemented yet is not that the value, but rather the complexity of the type system implementation. the transformation it self is rather trivial, i.e. {...x} into Object.assign({}, x). the issue is how these types are pretested and how they behave. for instance for a generic type parameter T is {...T} assignable to T, what about {x: number, ...T}, what about if T has methods, etc.. #10727 provides a more in depth explanation of the type system changes needed.

Contributor

mhegazy commented Sep 22, 2016

Updated the tags. I should clarify that the reason this has not been implemented yet is not that the value, but rather the complexity of the type system implementation. the transformation it self is rather trivial, i.e. {...x} into Object.assign({}, x). the issue is how these types are pretested and how they behave. for instance for a generic type parameter T is {...T} assignable to T, what about {x: number, ...T}, what about if T has methods, etc.. #10727 provides a more in depth explanation of the type system changes needed.

@pelotom

This comment has been minimized.

Show comment
Hide comment
@pelotom

pelotom Sep 22, 2016

I fully appreciate that the type system augmentations required for an ideal treatment of this feature are not trivial, and it's great to see that they are being enthusiastically tackled! I would just reiterate that,

putting in place the syntactic support for property spreads + naive typing of Object.assign would be a very helpful stopgap while we wait for the "right" implementation. Don't let perfect be the enemy of good.

pelotom commented Sep 22, 2016

I fully appreciate that the type system augmentations required for an ideal treatment of this feature are not trivial, and it's great to see that they are being enthusiastically tackled! I would just reiterate that,

putting in place the syntactic support for property spreads + naive typing of Object.assign would be a very helpful stopgap while we wait for the "right" implementation. Don't let perfect be the enemy of good.

@filipesilva

This comment has been minimized.

Show comment
Hide comment
@filipesilva

filipesilva Oct 2, 2016

Contributor

It seems like the proposal has reached stage 3: https://github.com/tc39/proposals

Contributor

filipesilva commented Oct 2, 2016

It seems like the proposal has reached stage 3: https://github.com/tc39/proposals

@bloadvenro

This comment has been minimized.

Show comment
Hide comment
@bloadvenro

bloadvenro Oct 7, 2016

@ddaghan your example with tsx won't work

@ddaghan your example with tsx won't work

@mhegazy mhegazy modified the milestones: TypeScript 2.1, TypeScript 2.1.2 Oct 27, 2016

@sandersn sandersn referenced this issue Nov 3, 2016

Merged

Object rest #12028

@SpyMaster356

This comment has been minimized.

Show comment
Hide comment
@SpyMaster356

SpyMaster356 Nov 5, 2016

any timeframe for this feature?

any timeframe for this feature?

@dsifford

This comment has been minimized.

Show comment
Hide comment
@dsifford

dsifford Nov 5, 2016

Contributor

@SpyMaster356 I've been lurking this for a while and it looks like it's close. @sandersn has been kicking ass on this for (at least) the past few weeks. 🙌

You can follow along here (#12028) and here (#11150)

Contributor

dsifford commented Nov 5, 2016

@SpyMaster356 I've been lurking this for a while and it looks like it's close. @sandersn has been kicking ass on this for (at least) the past few weeks. 🙌

You can follow along here (#12028) and here (#11150)

@sandersn sandersn closed this in #11150 Nov 10, 2016

@mhegazy mhegazy added the Fixed label Nov 10, 2016

@xooxdoo

This comment has been minimized.

Show comment
Hide comment
@xooxdoo

xooxdoo Nov 12, 2016

Some one should update the Roadmap

xooxdoo commented Nov 12, 2016

Some one should update the Roadmap

@kitsonk kitsonk referenced this issue in dojo/meta Nov 15, 2016

Closed

Migrate to TypeScript 2.1 #111

@aaronbeall

This comment has been minimized.

Show comment
Hide comment
@aaronbeall

aaronbeall Dec 7, 2016

It seems that using this feature allows the assignment of unknown props:

interface State {
  a: string;
  b: number;
}

let state: State = { a: "a", b: 0 };

state = {...state, x: "x"}; // No error

I was expecting an error that x is not a known property of State. Is this not how the feature works?

For example, my current workaround before this PR was this:

state = update(state, { x: "x" }); // Error: Property 'x' is missing in type 'State'.

function update<S extends C, C>(state: S, changes: C): S {
  return Object.assign({}, state, changes);
}

Is it possible to achieve this with object spread/rest?

aaronbeall commented Dec 7, 2016

It seems that using this feature allows the assignment of unknown props:

interface State {
  a: string;
  b: number;
}

let state: State = { a: "a", b: 0 };

state = {...state, x: "x"}; // No error

I was expecting an error that x is not a known property of State. Is this not how the feature works?

For example, my current workaround before this PR was this:

state = update(state, { x: "x" }); // Error: Property 'x' is missing in type 'State'.

function update<S extends C, C>(state: S, changes: C): S {
  return Object.assign({}, state, changes);
}

Is it possible to achieve this with object spread/rest?

@mhegazy

This comment has been minimized.

Show comment
Hide comment
@mhegazy

mhegazy Dec 7, 2016

Contributor

Object Rest and Spread, as per the ES proposal, behaves similar to Object.assign. the last mention of the property "wins". no errors are reported. in the example you had, the type of {...state, x:"X"} is { a: string, b:number, x:string }; and this type is assignable to State and thus the assignment works. this is the same as saying let state: State = { a: "a", b:0, x: "X" }; would be allowed as well.

Contributor

mhegazy commented Dec 7, 2016

Object Rest and Spread, as per the ES proposal, behaves similar to Object.assign. the last mention of the property "wins". no errors are reported. in the example you had, the type of {...state, x:"X"} is { a: string, b:number, x:string }; and this type is assignable to State and thus the assignment works. this is the same as saying let state: State = { a: "a", b:0, x: "X" }; would be allowed as well.

@aaronbeall

This comment has been minimized.

Show comment
Hide comment
@aaronbeall

aaronbeall Dec 7, 2016

But that's what I'm confused about: let state: State = { a: "a", b:0, x: "X" } gives the error Object literal may only specify known properties, and 'x' does not exist in type 'State' which is what I want... why is it a valid assignment when coming out of an object literal containing a spread?

aaronbeall commented Dec 7, 2016

But that's what I'm confused about: let state: State = { a: "a", b:0, x: "X" } gives the error Object literal may only specify known properties, and 'x' does not exist in type 'State' which is what I want... why is it a valid assignment when coming out of an object literal containing a spread?

@mhegazy

This comment has been minimized.

Show comment
Hide comment
@mhegazy

mhegazy Dec 7, 2016

Contributor

sorry.. object literals are a special case. my example was wrong. here is a better example:

let obj = { a: "a", b:0, x: "X" };
let state: State = obj; // OK

The issue here is if rather subjective. When the compiler sees let state:State = { a: "a", b:0, x: "X" }, chances are x is a typo, either a stale propoerty that was left off after refactoring, or a type for an optional property, that is why it is reported as an error.

however, if you spread an object, let's say let myConfig : State= { a: 1, ...myOtherBigConfigBag}, if the myOtherBigConfigBag has a few properties that you do not care about, you just need the a and the b, an error here would force you to keep these two interfaces in sync, or cast to make these errors go away.

that said. we should reconsider this decision. filed #12717 to track that.

Contributor

mhegazy commented Dec 7, 2016

sorry.. object literals are a special case. my example was wrong. here is a better example:

let obj = { a: "a", b:0, x: "X" };
let state: State = obj; // OK

The issue here is if rather subjective. When the compiler sees let state:State = { a: "a", b:0, x: "X" }, chances are x is a typo, either a stale propoerty that was left off after refactoring, or a type for an optional property, that is why it is reported as an error.

however, if you spread an object, let's say let myConfig : State= { a: 1, ...myOtherBigConfigBag}, if the myOtherBigConfigBag has a few properties that you do not care about, you just need the a and the b, an error here would force you to keep these two interfaces in sync, or cast to make these errors go away.

that said. we should reconsider this decision. filed #12717 to track that.

@aaronbeall

This comment has been minimized.

Show comment
Hide comment
@aaronbeall

aaronbeall Dec 8, 2016

I see. I love your idea in #12717, that's exactly what I was thinking. I would actually like such behavior even for the spread props but I can see your point that it's very subjective and might be annoying for some common JS use cases.

I see. I love your idea in #12717, that's exactly what I was thinking. I would actually like such behavior even for the spread props but I can see your point that it's very subjective and might be annoying for some common JS use cases.

@bondz

This comment has been minimized.

Show comment
Hide comment
@bondz

bondz Dec 8, 2016

@aaronbeall I agree, it would be annoying for common JS use cases... Most of the time, you just want to ensure the object has the shape of the interface specified and not directly inspect the spread object, the current implementation is okay IMO

bondz commented Dec 8, 2016

@aaronbeall I agree, it would be annoying for common JS use cases... Most of the time, you just want to ensure the object has the shape of the interface specified and not directly inspect the spread object, the current implementation is okay IMO

@olmobrutall

This comment has been minimized.

Show comment
Hide comment
@olmobrutall

olmobrutall Dec 8, 2016

Hi guys, Congrats for the great release! Now is time for a deserved rest... speacking of whitch I've an issue with the rest operator :)

Using React you tipically have a component like:

export interface MyLinkProps extends React.HTMLAttributes {
    myUrl: string
}

class MyLink{

    render(){
      const {myUrl, ...attrs } = this.props;
     return <a href={calculate(myUrl)} ...attrs>Click here</a>;
   }
}

The issue is that when you hover with the mouse over attrs you get the list of all the properties (hundreds) instead of React.HtmlAttributes.

I know that typescript is structurally typed and all that, but could be possible to assign an explicit type to the rest variable?

Some alternatives:

    const {myUrl, ...attrs as React.HtmlAttributes } = this.props; //Is not really a casting

    const {myUrl, ...attrs : React.HtmlAttributes } = this.props; //conflicts with ES6?
  
    const attrs : React.HTMLAttributes; 
    const { myUrl, ...attrs } = this.props;  //re-declare the variable

Hi guys, Congrats for the great release! Now is time for a deserved rest... speacking of whitch I've an issue with the rest operator :)

Using React you tipically have a component like:

export interface MyLinkProps extends React.HTMLAttributes {
    myUrl: string
}

class MyLink{

    render(){
      const {myUrl, ...attrs } = this.props;
     return <a href={calculate(myUrl)} ...attrs>Click here</a>;
   }
}

The issue is that when you hover with the mouse over attrs you get the list of all the properties (hundreds) instead of React.HtmlAttributes.

I know that typescript is structurally typed and all that, but could be possible to assign an explicit type to the rest variable?

Some alternatives:

    const {myUrl, ...attrs as React.HtmlAttributes } = this.props; //Is not really a casting

    const {myUrl, ...attrs : React.HtmlAttributes } = this.props; //conflicts with ES6?
  
    const attrs : React.HTMLAttributes; 
    const { myUrl, ...attrs } = this.props;  //re-declare the variable
@aaronbeall

This comment has been minimized.

Show comment
Hide comment
@aaronbeall

aaronbeall Dec 8, 2016

@bondz Well, its not true in 100% of the uses in my project. :) But in another project it may be very annoying. In my case I'm using Redux and React and making heavy use of immutable state, which means to update or create state objects I must copy all props onto a new object literal... in all cases I want 100% type safety that I'm trying to copy the right data onto the target state interface. Currently I use functions to ensure this safety, but I would prefer to use object spread because its cleaner (readable, expressive, standard syntax.) But in someone else's project they might want different behavior because they are using a lot of untyped or loose object structures, so I see how it's quite subjective. I think the #12717 suggestion is a good middle ground (and more consistent with existing object literal type safety.)

aaronbeall commented Dec 8, 2016

@bondz Well, its not true in 100% of the uses in my project. :) But in another project it may be very annoying. In my case I'm using Redux and React and making heavy use of immutable state, which means to update or create state objects I must copy all props onto a new object literal... in all cases I want 100% type safety that I'm trying to copy the right data onto the target state interface. Currently I use functions to ensure this safety, but I would prefer to use object spread because its cleaner (readable, expressive, standard syntax.) But in someone else's project they might want different behavior because they are using a lot of untyped or loose object structures, so I see how it's quite subjective. I think the #12717 suggestion is a good middle ground (and more consistent with existing object literal type safety.)

@evisong

This comment has been minimized.

Show comment
Hide comment
@evisong

evisong Dec 16, 2016

#2103 (comment)
We want to wait for the proposal to reach Stage 3 before addressing this.

Seems it's already state 3, any plan of supporting this?

Btw, we use VSCode mainly for ES development, not TS yet :)

evisong commented Dec 16, 2016

#2103 (comment)
We want to wait for the proposal to reach Stage 3 before addressing this.

Seems it's already state 3, any plan of supporting this?

Btw, we use VSCode mainly for ES development, not TS yet :)

@bondz

This comment has been minimized.

Show comment
Hide comment
@bondz

bondz Dec 16, 2016

@evisong this feature has shipped and is already available in the latest version of vsCode. Update your vsCode to version 1.8

bondz commented Dec 16, 2016

@evisong this feature has shipped and is already available in the latest version of vsCode. Update your vsCode to version 1.8

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.