@typedefs with values

102 views
Skip to first unread message

John Lenz

unread,
May 17, 2013, 11:37:26 AM5/17/13
to Nick Santos, dim...@google.com, closure-compiler
There has been a couple of attempt to use @typedefs in unique ways recently and we need to decide if we want to encourage or discourage these practices:

case 0: standard practice

/** @typedef {string} */  var X;

case 1: type alias

/** @typedef {Foo} */ var Bar = Foo;

case 2: namespace with a type

/** @typedef {string} */ var Bar = {};
Bar.X = 1;

case 3: random value

/** @typedef {string} */ var Bar = true;
/** @typedef {Foo} */ var Bar = new Foo()


0 obviously we support, 1 seems natural enough and I'm working on fixing collapse properties so this actually works.  

Case 2, has some use and works today but I'm concerned that we might be incurring engineering debt if we allow it.  

Case 3, seems most likely typos and we should ban them

John Lenz

unread,
May 17, 2013, 11:38:17 AM5/17/13
to Nick Santos, dimvar, closure-compiler, malt...@gmail.com
+malte

Dimitris Vardoulakis

unread,
May 17, 2013, 11:51:31 AM5/17/13
to John Lenz, Nick Santos, closure-compiler, malt...@gmail.com
I don't get case 1. Should it be
/** @typedef {Foo} */ var Foo = Bar;
??
If not, where else is Foo defined and can appear as an rvalue here?

If yes, can't we just write
/** @typedef {Bar} */ var Foo;
and get the same thing?

Also, I don't think we should support 2 and 3. Typedef is meant to be a shorthand for an already defined type, and that's it. (I don't have an opinion on case 1 yet b/c I don't fully understand what it does.)
--
Dimitris

Nick Santos

unread,
May 17, 2013, 12:04:16 PM5/17/13
to John Lenz, Dimitris Vardoulakis, closure-compiler
That's odd. I thought we used to explicitly forbid 1-3, by giving
the typedef variable a NoneType. Did that break?

Chad Killingsworth

unread,
May 17, 2013, 2:08:08 PM5/17/13
to closure-comp...@googlegroups.com, John Lenz, Nick Santos, malt...@gmail.com
John: In case 1, does that work with anonymous types? If so, that should solve https://code.google.com/p/closure-compiler/issues/detail?id=448
 
I don't understand what's going on in case 2. I agree that case 3 should not be allowed.
 
Chad

John Lenz

unread,
May 17, 2013, 4:55:14 PM5/17/13
to Nick Santos, Dimitris Vardoulakis, closure-compiler
If so, it has been broken for a while.

John Lenz

unread,
May 17, 2013, 4:58:48 PM5/17/13
to closure-compiler, Nick Santos, Malte Ubl
Clarification for 

Case 1:

/** @constructor */
function NewName() {}

/** @typedef {NewName} */
var OldName = NewName;

var y = new NewName();
goog.asserts.assert(y instanceof OldName);






--
 
---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Dimitris Vardoulakis

unread,
May 17, 2013, 5:00:45 PM5/17/13
to closure-comp...@googlegroups.com, Nick Santos, Malte Ubl
Thanks for the clarification John. Now that I understand, my opinion is that we shouldn't support case 1.
--
Dimitris

John Lenz

unread,
May 17, 2013, 5:02:35 PM5/17/13
to closure-compiler, Nick Santos, Malte Ubl
Can you outline your line of reasoning?  This is the one case I would like to support.

Dimitris Vardoulakis

unread,
May 17, 2013, 5:07:22 PM5/17/13
to closure-comp...@googlegroups.com, Nick Santos, Malte Ubl
Typedef usually introduces a new type name as an alias for an existing type. Can we get what case 1 does by writing

/** @type {NewName} */
var OldName = NewName;

instead of 

/** @typedef {NewName} */
var OldName = NewName;

?

Nick Santos

unread,
May 17, 2013, 5:13:14 PM5/17/13
to John Lenz, closure-compiler, Malte Ubl
We already support:
/** @constructor */ var Foo = Bar;
and
/** @enum */ var Foo = Bar;

right?

Using @typedef for this makes it look like more complicated forms will
work, i.e.,
/** @typedef {Bar} */
var Foo = someExpr;
when in fact they will not.

John Lenz

unread,
May 17, 2013, 5:13:36 PM5/17/13
to closure-compiler, Nick Santos, Malte Ubl
no, @type is an instance of NewName.  @typedef declares it to be the Type.

Consider:

/** @type {String} */
var Alias = String;  // Error Function is not a String
new Alias(); // Error a String instance is not a constructor, can not be called with new.

/** @typedef {String} */
var Alias = String;  // no typecheck here
new Alias(); // Alias is a another name for the String constructor, ok.



Dimitris Vardoulakis

unread,
May 17, 2013, 5:15:50 PM5/17/13
to closure-comp...@googlegroups.com, Nick Santos, Malte Ubl
I see. What about Nick's examples? Would these be enough for the OldType/NewType aliasing? Or is there more to typedef-case1?

John Lenz

unread,
May 17, 2013, 5:25:10 PM5/17/13
to closure-compiler, Nick Santos, Malte Ubl
On Fri, May 17, 2013 at 11:08 AM, Chad Killingsworth <chadkill...@missouristate.edu> wrote:
John: In case 1, does that work with anonymous types? If so, that should solve https://code.google.com/p/closure-compiler/issues/detail?id=448

How would I refer to the anonymous type in typedef declaration?
 
 
I don't understand what's going on in case 2. I agree that case 3 should not be allowed.
 

In case 2, the type name and the slot type are different.  It is being used as a namespace.

I don't completely understand why it is useful either, except you can associate some values with the type.
 

--

John Lenz

unread,
May 17, 2013, 5:25:33 PM5/17/13
to closure-compiler, Nick Santos, Malte Ubl
Yes, I think Nick's examples are sufficient.  I'll try it out.

/** @const */
var OldNameSpace = NewNameSpace;

/** @constructor */
var OldConstructor = NewConstructor;

/** @enum */
var OldEnum = NewEnum;

Nick Santos

unread,
May 17, 2013, 5:29:51 PM5/17/13
to John Lenz, closure-compiler, Malte Ubl
I can certainly understand the argument that
/** @typedef {Bar} */ var Foo = Bar;
is just a more "intuitive" syntax for a constructor alias.

So I do think it would be reasonable to allow this, as long as we
clearly define what forms are allowed on the right-hand-side

But I also think it would be reasonable to forbid it if it really is
redundant with existing syntaxes.

John Lenz

unread,
May 17, 2013, 5:41:07 PM5/17/13
to Nick Santos, closure-compiler, Malte Ubl
For Case 1, I just want a syntax and I didn't think about use @constructor and @typedef worked for me but the other use cases made me concerned.  If we have other options, I happy to tighten down the definition.

Johannes Nel

unread,
May 20, 2013, 11:33:50 AM5/20/13
to closure-comp...@googlegroups.com
From what I have read, case 1 does not provide very good type checking at runtime (http://closuretools.blogspot.co.uk/2012/02/type-checking-tips.html), should case 1 not perhaps result in a warning. 

Cases 2 seems the product of bad type checking and although legit in JS should be banned imo, case 3 makes little sense since the compiler supports union types and if I see something like that I would assume it is a bug.
j:pn
\\no comment
Reply all
Reply to author
Forward
0 new messages