Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CS2 Discussion: Features: Support splats in object literals (object rest/spread syntax) #4959

Closed
coffeescriptbot opened this issue Feb 19, 2018 · 8 comments

Comments

@coffeescriptbot
Copy link
Collaborator

From @connec on 2016-12-15 18:31

I would love to see object spreads and rests supported via splats in object literals:

{ foo, rest... } = { foo: 1, bar: 2 }
console.log foo, rest # 1 { bar: 2 }
console.log { foo, rest... } # { foo: 1, bar: 2 }

obj = { foo: 1 }
copy = { ...obj }
console.log obj === copy # false

setName = (name, record) -> { name, record... }
console.log setName 'greeting', hello: 'world' # { name: 'greeting', hello: 'world' }

stripName = ({ name, record... }) -> record
console.log stripName name: 'greeting', hello: 'world' # { hello: 'world' }

Compilation in the 2 branch could happily use Object.assign for construction:

// console.log { foo, rest... }
console.log(Object.assign({ foo }, rest))

Destructuring would require more implementation, e.g.

// { foo, rest... } = { foo: 1, bar: 2 }
var ref, ref1, ref2, i, k, foo, rest
ref = { foo: 1, bar: 2 }
ref1 = Object.keys(ref)
ref2 = [ 'foo' ] // compiler-generated list of the non-splat properties
foo = ref.foo
rest = {}
for (i = 0; i < ref1.length; i++) {
  k = ref1[i]
  if (ref2.indexOf(k) < 0) {
    rest[k] = ref[k]
  }
}

We could alternatively wait for the proposal to land in environments, or rely on a transpiler like babel.

@coffeescriptbot
Copy link
Collaborator Author

From @JavascriptIsMagic on 2016-12-15 20:41

I've been seeing object spread being recommended and I've seen it being used heavily in large production code bases. I find myself using Object.assign quite a bit myself in situations where I would have much cleaner code using object spread, and it is such a nice compliment to the array... spread


I think this does require you to use the {brackets} in the syntax or it will get ambiguous with the array... spread:

fun a: 1, b...   # ambiguous
fun {a: 1, b...} # unambiguous

Also do we go with the spec and put the operator on the left { ...spread } or go with coffeescripty { spread... } ?

One benefit to having it go in the opposite direction would be that it could disambiguate the two and we could get rid of the need for {brackets}

# object spread:
fun a: 1, ...b # fun({ a: 1, ...b })
# argument spread:
fun a: 1, b... # fun({ a: 1 }, ...b)

Though consistency of the spread syntax might be preferred over getting rid of ambiguity.

@coffeescriptbot
Copy link
Collaborator Author

From @connec on 2016-12-15 21:07

I'd definitely vote for consistency over that ambiguity, though it is an annoying one. Ultimately I suppose it's consistent with needing explicit braces to have shorthand objects in arguments lists too.

f a: a, b     # f({ a: a }, b)
f { a: a, b } # f({ a: a, b: b })

@coffeescriptbot
Copy link
Collaborator Author

From @YamiOdymel on 2017-02-22 15:41

I'd recommend to put the ... in front of the object, variable,

so you can spread an object from the function like this (This is very common in Vuex, Redux):

export default {
    name: 'CounterBlock'
    methods:
        ...mapActions
            increment : counter.actions.increment,
            set       : counter.actions.set,
            fetchCount: counter.actions.fetchCount
    computed:
        ...mapGetters
            total: counter.getters.total
}

currently with [email protected] there's no spread operator, so you would have to use Object.assign({}, obj1, obj2) instead.

export default {
    name: 'CounterBlock'
    methods: Object.assign {}, mapActions
            increment : counter.actions.increment,
            set       : counter.actions.set,
            fetchCount: counter.actions.fetchCount
    computed: Object.assign {}, mapGetters
            total: counter.getters.total
}

with ECMAScript6

export default {
    name: 'CounterBlock',
    methods: {
        ...mapActions({
            increment : counter.actions.increment,
            set       : counter.actions.set,
            fetchCount: counter.actions.fetchCount
        })
    },
    computed: {
        ...mapGetters ({
            total: counter.getters.total
        })
    },
}

@coffeescriptbot
Copy link
Collaborator Author

From @GeoffreyBooth on 2017-07-25 05:28

Added via #4493

@coffeescriptbot
Copy link
Collaborator Author

From @chabib on 2017-10-14 18:51

@GeoffreyBooth @YamiOdymel
After #4493, how can we get below code now?

...mapActions({
  increment : counter.actions.increment,
  set       : counter.actions.set,
  fetchCount: counter.actions.fetchCount
})

@coffeescriptbot
Copy link
Collaborator Author

From @YamiOdymel on 2017-10-14 19:13

@chabib Well, if I'm not mistaken, you could use it like this.

object = {
    ...mapActions
        increment : counter.actions.increment,
        set       : counter.actions.set,
        fetchCount: counter.actions.fetchCount
}

Which produces:

var object, _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; };

object = _extends({}, mapActions({
      increment: counter.actions.increment,
      set: counter.actions.set,
      fetchCount: counter.actions.fetchCount
}));

is the same as below with ECMAScript6

object = {
    ...mapActions({
        increment : counter.actions.increment,
        set       : counter.actions.set,
        fetchCount: counter.actions.fetchCount
    })
}

@coffeescriptbot
Copy link
Collaborator Author

From @chabib on 2017-10-14 19:25

Thank you @YamiOdymel !
Looks like we can do this

export default
  computed: {
    ...mapActions
        increment : counter.actions.increment,
        set       : counter.actions.set,
        fetchCount: counter.actions.fetchCount
  }

But not this

export default
  computed:
    ...mapActions
        increment : counter.actions.increment,
        set       : counter.actions.set,
        fetchCount: counter.actions.fetchCount

@coffeescriptbot
Copy link
Collaborator Author

From @YamiOdymel on 2017-10-14 19:42

@chabib I asked about this in #4449

Keyless property requires explicit braces - {}.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant