HoriSun / closure-compiler

Automatically exported from code.google.com/p/closure-compiler
0 stars 0 forks source link

Unable to specify a constructor function with an arbitrary number of parameters #1248

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I'm trying to specify a constructor function with a constructor that takes any 
number of parameters:
/** @typedef {function(new:T, ...[*])} */
var AnyConstructor;

However a concrete constructor instance that takes e.g. one parameter does not 
satisfy that type, e.g. {function(new:MyClass, number)} is not a subtype of 
AnyConstructor.

It's possible to have the compiler accept this by specifying ...[?], but that 
doesn't seem right either?

Original issue reported on code.google.com by martinpr...@google.com on 19 Feb 2014 at 4:46

GoogleCodeExporter commented 9 years ago
Probably I wasn't clear in our earlier discussion. The type that you have 
specified for AnyConstructor does what you want. However, the correct subtyping 
behavior for functions doesn't work how you expect.

function(...[SomeType]) is a subtype of a function(SomeType), not the other way 
around. You can use a function that can handle an arbitrary number of arguments 
in a context that will pass it only one argument.

The fact that function(...[?]) worked for your example is a compiler bug.

Original comment by dim...@google.com on 19 Feb 2014 at 5:49

GoogleCodeExporter commented 9 years ago
What I'm saying is: I want to express "A constructor function taking any 
arguments". That appears to be impossible in JSCompiler, right?

If so, I think that's a valid feature request, wouldn't you agree?

Original comment by martinpr...@google.com on 19 Feb 2014 at 5:54

GoogleCodeExporter commented 9 years ago
It's not impossible; it's the type you've already written. But it's not a 
supertype of all other constructors, it's a subtype of all of them.

The subtyping behavior that you want is not correct.

Original comment by dim...@google.com on 19 Feb 2014 at 6:30

GoogleCodeExporter commented 9 years ago
How do I write a type that is a supertype of all constructors, while capturing 
what type it will construct for an @template type?

Original comment by martinpr...@google.com on 19 Feb 2014 at 8:33

GoogleCodeExporter commented 9 years ago
That type you can't write. It's not even possible to write a supertype of all 
constructors. The closest you can get is Function, which is the supertype of 
all functions.

Original comment by dim...@google.com on 19 Feb 2014 at 9:10

GoogleCodeExporter commented 9 years ago
I should also mention that using Function allows you to do many unsound things 
without warning, eg,

/** @param {Function} x */
function f(x) {
  x();
  new x();
}

/** @param {number} n */
function g(n) {};

f(g);

so we don't plan to add another type like that as a supertype of all 
constructors.

Original comment by dim...@google.com on 19 Feb 2014 at 9:12

GoogleCodeExporter commented 9 years ago
According to other discussion, the correct way to write this is
function(new:T, ...[?]). Can you confirm that, or am I misunderstanding the
discussion? Just want to document the correct way here.

2014-02-19 22:12 GMT+01:00 <closure-compiler@googlecode.com>:

Original comment by martinpr...@google.com on 20 Feb 2014 at 8:28

GoogleCodeExporter commented 9 years ago
It's safe to use this for now. If we end up changing it in the future, we'll 
probably provide an alternative.

Original comment by dim...@google.com on 20 Feb 2014 at 8:58