Skip to content

Spread operator in 'new' expressions support for ES5? #2369

Closed

Description

I've found that #1931 supports this only for ES6, but it seems ES5 also can do this in any way.

var arguments = [1, 2, 3, 4, 5];
new Array(...arguments);

This can be converted to ES5:

// Thanks to: http://stackoverflow.com/a/14378462/2460034
var arguments = [1, 2, 3, 4, 5];
new (Array.bind.apply(Array, [null].concat(arguments)));
// Result: [1, 2, 3, 4, 5]

Activity

  1. RyanCavanaugh commented on Mar 17, 2015

    @RyanCavanaugh
    Member

    Seems reasonable enough.

  2. added this to the milestone on May 4, 2015
  3. RyanCavanaugh commented on May 4, 2015

    @RyanCavanaugh
    Member

    Approved. Be sure to handle the case where the operand to new is a computed expression that needs to be cached in a temporary variable.

  4. tinganho commented on May 7, 2015

    @tinganho
    Contributor

    I'm almost done with a PR on this one. Though there are one issue with the type checker:

    interface ObjectWithSpreadMethod {
        spreadMethod(x: number, y: number, ...z: string[]);
    }
    
    var spread: string[];
    var objectWithSpreadMethod: ObjectWithSpreadMethod;
    
    new objectWithSpreadMethod.spreadMethod(1, 2, "string");
    new objectWithSpreadMethod.spreadMethod(1, 2, ...spread);
    new objectWithSpreadMethod.spreadMethod(1, 2, ...spread, "string"); 

    Isn't it correct TS code above? Why can't I do new objectWithSpreadMethod.spreadMethod on a method?

    Shall I correct this behavior?

    Playground:
    http://www.typescriptlang.org/Playground#src=interface%20ObjectWithSpreadMethod%20%7B%0D%0A%20%20%20%20spreadMethod(x%3A%20number%2C%20y%3A%20number%2C%20...z%3A%20string%5B%5D)%3B%0D%0A%7D%0D%0A%0D%0Avar%20spread%3A%20string%5B%5D%3B%0D%0Avar%20objectWithSpreadMethod%3A%20ObjectWithSpreadMethod%3B%0D%0A%0D%0Anew%20objectWithSpreadMethod.spreadMethod(1%2C%202%2C%20%22string%22)%3B%0D%0Anew%20objectWithSpreadMethod.spreadMethod(1%2C%202%2C%20...spread)%3B%0D%0Anew%20objectWithSpreadMethod.spreadMethod(1%2C%202%2C%20...spread%2C%20%22string%22)%3B%20

  5. RyanCavanaugh commented on May 7, 2015

    @RyanCavanaugh
    Member

    Seems like it should be typed like this:

    interface ObjectWithSpreadMethod {
        spreadMethod: {
            new (x: number, y: number, ...z: string[])
        };
    }

    Alternatively:

    interface ObjectWithSpreadMethod {
        spreadMethod(x: number, y: number, ...z: string[]): void;
    }

    The code as written has spreadMethod returning any, which is not a valid invocation target for new.

  6. tinganho commented on May 7, 2015

    @tinganho
    Contributor

    Ryan Cavanaugh (@RyanCavanaugh) Ok thanks, I will land a PR later.

  7. modified the milestones: TypeScript 1.6, on May 18, 2015
  8. mhegazy commented on May 18, 2015

    @mhegazy
    Contributor
  9. mdcone commented on Aug 20, 2015

    @mdcone

    Does this seem to just be a happy coincidence with Array? Using this technique with my own TS classes doesn't work.

    Seems as if it really is impossible. According to MDN --

    Apply for new

    Example: In ES5 it is not possible to compose new with apply (in ES5 terms apply does a [[Call]] and
    not a [[Construct]]). In ES6 the spread syntax naturally supports this.
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

    Further reading into the ES6 standard:

    The Array constructor is the %Array% intrinsic object and the initial value of the Array property of the global object. When called as a constructor it creates and initializes a new exotic Array object. When Array is called as a function rather than as a constructor, it also creates and initializes a new Array object. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments.

    Which tells me that using something that does a [[Call]] with an array (.apply() or .call()) also has the same effect as a [[Construct]].

    I'm fine with allowing this behavior in this case, so maybe allowing for a warning to be emitted instead of an error, or for special casing the errors to give a hint to the programmer as to why a program isn't behaving as expected might be a useful thing.

  10. tinganho commented on Aug 20, 2015

    @tinganho
    Contributor

    mdcone could you share your classes? I tested it with TS classes and it seems to work for me.

  11. locked and limited conversation to collaborators on Jun 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions