6

I am preparing externs for PIXI.js library. I am getting the following warning:

js/Test.js:188: WARNING - Property position never defined on PIXI.Sprite
        button.position.y = y;

Here are the relevant extern definitions:

//UPDATE

/** 
 * @constructor
 * @extends {PIXI.Container} 
 * @param {PIXI.Texture} texture
 */
PIXI.Sprite = function(texture){};

/** 
 * @constructor
 * @extends {PIXI.DisplayObject} 
 */
PIXI.Container = function(){};

/**
 * @constructor 
 * @extends {PIXI.EventEmitter} 
 */
PIXI.DisplayObject = function(){};

/**
 * @type {PIXI.Point}
 */
PIXI.DisplayObject.position;

Still getting the same warning.

What am I doing wrong?

When I am replacing PIXI.DisplayObject.position; with PIXI.DisplayObject.prototype.position; that seems to clear the warning.

Does it mean that I should always define SomeObject.prototype.prop rather then SomeObject.prop ?

James May
  • 516
  • 2
  • 11
  • Closure-compiler doesn't understand the `@member`, `@memberof` or `@class` annotations. Also, your `@extends` annotations need braces: `@extends {parentType}`. This is the reference of annotations the compiler understands: https://developers.google.com/closure/compiler/docs/js-for-compiler – Chad Killingsworth Dec 09 '15 at 02:17
  • @ChadKillingsworth Thank you for you comment, I did the corrections, still getting the same warning. I updated the question. It seems to work if I add `prototype`. Should I always define `SomeObject.prototype.prop` rather `then SomeObject.prop` ? – James May Dec 09 '15 at 18:32

1 Answers1

1

This is highlighting the difference between static and prototype properties.

Given:

/**
  * @constructor
  * @param {number=} opt_num
  */
function foo(opt_num) {
    if (opt_num !== undefined) {
        this.bar = opt_num;
    }
}
foo.prototype.bar = 17;
foo.bar = 42;

We have both a static property and a prototype property of the same name. However they are referenced differently:

console.log((new foo()).bar); // 17
console.log((new foo(0)).bar); // 0
console.log(foo.bar); // 42

So in an extern, when you are defining properties on a type - you typically want to define them on the prototype object:

/** @param {foo} obj_foo */
function log(obj_foo) {
   // This is an instance of "foo".
   // The "bar" property references prototype or instance
   // properties - not static properties.
   console.log(obj_foo.bar);

   // Static properties can only be referenced by the full namespace
   console.log(foo.bar);
}
Chad Killingsworth
  • 14,360
  • 2
  • 34
  • 57
  • Thank you for shedding helpful light on the subject :) I have looked through few externs files and I noticed in https://github.com/google/closure-compiler/blob/master/contrib/externs/jquery-1.9.js there are few definitions for @private functions and I am curious what is the use of that if these supposed to be private? – James May Dec 09 '15 at 22:29
  • It's a "trick" in externs. It's a type that is created by another function. It's an old style. Now we just use interfaces as they can't be created directly anyway. – Chad Killingsworth Dec 09 '15 at 22:31