Annotation Problem - How to declare a returned function with dynamically attached properties ?

87 views
Skip to first unread message

Bernd Wessels

unread,
May 28, 2012, 2:05:29 AM5/28/12
to closure-lib...@googlegroups.com
Hi guys,

I am trying to figure out the right annotation for the following code:

goog.provide('goog.observable');

/**
 * @interface
 * @param {*=} opt_value
 */
goog.iObservable = function(opt_value) {};
/**
 * @type {number}
 */
goog.iObservable.prototype.subscriptionID;
/**
 * @type {Object}
 */
goog.iObservable.prototype.subscriptions;
/**
 * @type {function(function(*))}
 */
goog.iObservable.prototype.subscribe;
/**
 * @type {function(function(*))}
 */
goog.iObservable.prototype.unsubscribe;

/**
 * @param {*} initValue
 * @returns {??????????}
 */
goog.observable = function(initValue) {
var currentValue = initValue;
var observable = null;
observable = (function() {
if (arguments.length > 0) {
currentValue = arguments[0];
for ( var key in observable.subscriptions) {
observable.subscriptions[key](arguments[0]);
}
} else {
return currentValue;
}
});
observable.subscriptionID = 0;
observable.subscriptions = {};
observable.subscribe = function(callback) {
observable.subscriptions[observable.subscriptionID++] = callback;
return observable.subscriptionID - 1;
};
observable.unsubscribe = function(subscriptionID) {
if (observable.subscriptions[subscriptionID]) {
observable.subscriptions[subscriptionID] = null;
delete observable.subscriptions[subscriptionID];
}
};
return observable;
};

It should be uses like that:

goog.require('goog.observable');
function test() {
var person = {
name: goog.observable('john'),
age: goog.observable(37)
};
var test = person.name();
alert(test);
var sid1 = person.name.subscribe(function(newValue){
alert(newValue);
});
var sid2 = person.age.subscribe(function(newValue){
alert(newValue);
});
person.name('james');
person.age(36);
person.name.unsubscribe(sid1);
person.name.unsubscribe(sid2);
}

I tried so many different annotations, but always get compiler errors - Only if I remove the @returns from goog.observable it compiles, but I would rather prefer to figure out how to annotate it correctly.

Can anybody please tell me what is the right annotation for the return value of goog.observable.

Thank you
Bernd

PS: I know I shouldn't use goog as the namespace for my goog.observable ;)

Guido Tapia

unread,
May 28, 2012, 4:04:05 AM5/28/12
to closure-lib...@googlegroups.com
You can just do:
@return {goog.iObservable}

But you will have to cast your assignment, i.e:
var observable = (function...

Will become:
var observable = /** @type {goog.iObservable} */ (function


Bernd Wessels

unread,
May 28, 2012, 6:05:48 PM5/28/12
to closure-lib...@googlegroups.com
Sorry, that is WRONG. If it were that easy I would not have asked here ;)

Here is what happens if we try your suggestion:

ERROR - goog.iObservable expressions are not callable
     [exec] var s = person.name();

The issue is a bit more complicated. Since the returned observable is not a typical instance of a function as described in iObservable, the compiler refuses  it to be called in the way I showed in my example.

So please, any Closure Guru out there who can help me on that ?

Best regards
Bernd


PS: I usually try many possible scenarios before I go and ask a question here. So believe me that I really tried all the obvious ways to solve this.

Carsten Kraus

unread,
May 29, 2012, 7:28:38 AM5/29/12
to closure-lib...@googlegroups.com

maggie....@gmail.com

unread,
May 29, 2012, 1:02:38 PM5/29/12
to closure-lib...@googlegroups.com
Any reason the iObservable is not a constructor function? if you just created iObserable objects then everything should work out. Otherwise I'm sure you tried @return {Function}, but what was the issue with that? Also it should be @return not @returns

Nick Santos

unread,
May 29, 2012, 5:34:37 PM5/29/12
to closure-lib...@googlegroups.com
right, i don't believe there's currently a way to specify a function
with properties. The best you can do is {Function}

Nick

Bernd Wessels

unread,
May 29, 2012, 6:56:56 PM5/29/12
to closure-lib...@googlegroups.com
Hi Nick

Thank you, I tried almost everything but I guess you are right that there is no way for this specific scenario.

I would prefer not doing it the way I did and I understand that this is a strange case, which might be why  there is no annotation pattern for it at the moment.

But the reason why I am doing it is just that is is a very elegant way to be used without the need of accessing the property via key. At least I couldn't find another way of achiving: myModel.aProperty.subscribe(function(newValue){...}); But this might be a complete different discussion ;)

Thanks anyway.
Bernd

PS Thanks to Carsten as well, interesting link ;)
Reply all
Reply to author
Forward
0 new messages