16

Using optional chaining with function calls causes the expression to automatically return undefined instead of throwing an exception if the method isn't found.

Note: The code is using spread syntax, not rest parameters.

const fn1 = undefined
const args = []
const fn2 = () => {}
const fn3 = () => {}

console.log(fn1?.(...args, fn2, fn3))

Error:

console.log(fn1?.(...args, fn2, fn3))
                                ^
TypeError: Function.prototype.apply was called on undefined, which is an undefined and not a function
Wenfang Du
  • 8,804
  • 9
  • 59
  • 90
  • 2
    The problem appears only when `...args` appears anywhere else other than the end in the function call. Weird. – maazadeeb Mar 13 '21 at 03:03
  • 1
    It's weird that we get this error. Normally, you'ed get a "fn1 is not a function" error. This error shows up even when not using optional chaining. Compare: `(() => { ({test: undefined}).test(...([])) })() // Uncaught TypeError: {(intermediate value)}.test is not a function ` vs `(() => { ({test: undefined}).test(...([]), 1) })() // Uncaught TypeError: Function.prototype.apply was called on undefined, which is a undefined and not a function ` – Daniel Mar 13 '21 at 06:41
  • Looks like issue with chromium browsers, runs fine in Mozilla Firefox – Gowtham Raj J Mar 13 '21 at 06:46
  • 3
    This is definitely a bug - their experimental implementation of the optional chaining does not work with how they transpile calls with spread syntax. – Bergi Mar 13 '21 at 14:39

2 Answers2

10

It turns out to be a V8 bug, I've submitted it there, hopefully, it'll be fixed soon.

Update: it has been fixed.

Wenfang Du
  • 8,804
  • 9
  • 59
  • 90
-4

There are a couple rules to follow with ...rest arguments.

One of those rules is that the ...rest argument can only be the last argument.

foo(...one, ...wrong, ...wrong)
foo(...wrong, bad, bad)
foo(ok, ok, ...correct)

See:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters

bob
  • 7,539
  • 2
  • 46
  • 42
  • 10
    But the question is using spread, not rest. And spread parameters can come anywhere, any number of times – maazadeeb Mar 13 '21 at 03:06