JSDoc: Custom Types, Constructors

From what I have seen so far, if you want to define your own custom type in Servoy 7 with JSDocs, you must define a Scope variable with the name of your custom type, and use its @type declaration to talk about its properties. This still leaves you with the problem of creating a constructor for this type, but you can’t simply use the type name, you have to resort to something like this:

/**
 * @type {{name:String, status:Number}}
 * @properties={typeid:35,uuid:"144D2CC1-0386-472C-88EC-94A564C03C81",variableType:-4}
 */
var CustomType;

/**
 * @constructor 
 * @param {String} name
 * @param {Number} status
 * @return {scopes.mytypes.CustomType}
 * @properties={typeid:24,uuid:"BFF44032-25A3-4664-8415-1020FAB2D4F0"}
 */
function newCustomType(name, status) {
	var x = {
		name : name,
		status : status
	};
	return x;
}

It seems like a more natural way to accomplish this would to be to allow the referring directly to a constructor function as the type and to be able to use it’s @return signature as the type definition. This almost, kind of, works in a few edge cases, but in general falls down for normal usage.

/**
 * @constructor 
 * @param {String} name
 * @param {Number} status
 * @return {{name:String, status:Number}}
 * @properties={typeid:24,uuid:"BFF44032-25A3-4664-8415-1020FAB2D4F0"}
 */
function CustomType(name, status) {
	var x = {
		name : name,
		status : status
	};
	return x;
}

/**
 * @type {scopes.mytypes.CustomType}
 * @properties={typeid:35,uuid:"E85050E7-2738-4412-80A7-56B22E466539",variableType:-4}
 */
var defaultVal = CustomType("default",0);

/**
 * @param {scopes.mytypes.CustomType} x
 * @properties={typeid:24,uuid:"DE6836EA-C6AF-4AA0-80D5-66819CBC343B"}
 */
function doSomething(x) {
	application.output(x.name); //Warning: The property name is undefined in x
}

/**
 * @properties={typeid:24,uuid:"9E6165CE-E4FC-4EC8-B791-89C28FA35B0D"}
 */
function doThings() {
	doSomething(defaultVal); //This actually works and shows no warnings
	var m = CustomType("name", 10);
	doSomething(m); //Warning: The function doSomething(scopes.mytypes.CustomerType) is not applicable for the arguments {{name:String, status:Number}}
}

Given the existence of the @constructor tag it “feels” like Servoy wants us to be able to do things like this.
I know that I want to do things like this.

Can this be real life? Or is it just fantasy… :wink:

james,

as i explained in this case: https://support.servoy.com/browse/SVY-4744

/**
* @type {{name:String, status:Number}}
*/
var CustomType

thats not a custom type…
That is a variable that has as contents that type, so its the same as far a function to say @param {MyType} param
that also doesn’t mean that the param variable is a type. No its a variable holding something of that type.

what would below mean if we threat @type as a type definition:

/**
* @type {String}
*/
var CustomType

is this now that “CustomType” is an alias for “String” ?
No everybody understands that now CustomType is a variable holding a String…
So that is also what your example gave us.

For creating custom types i have made @typedef support in the next release of Servoy 7
We follow this: https://developers.google.com/closure/c … iler#types

/**
* @typedef {{name:String, status:Number}}
*/
var CustomType;

now you really defined a new custom type. Where the variable name is really a type instead of holding a value…

that function type where you do a return is looks very weird to me.
function types are just that, there are custom types where you can call a constructor on to create objects from. This is already supported in the latest Servoy releases.
But you seem to be using that quite weird, i would just do:

/**
* @constructor 
* @param {String} name
* @param {Number} status
*/
function CustomType(name, status) {
   this.name = name;
  this.status = status;
}

This is great information and clears up a lot of confusion I was having in regards to this the JSDoc system works. Thanks Johan!

I’m having some problems trying to define a global typedef, maybe I’m doing something wrong or it’s not possible.

What I want is to define a typedef like above on the globals file and then use it inside forms for example. Is it possible? My tests say it’s not.

Thanks in advance

Bump

There is already a case for using typedefs outside the scope where it is defined. For now, you could use @type instead. While that is not exactly what it should be, it should work.

can you quickly try in 812rc ? because i think we fixed something like this in that release.

Just tested, the problem persists.

In globals:

/**
 * @typedef {{ version:String, someProp: String, someProp2: String }}
 */
var MyType;

And then in some form of the same module:
/**
 * Test function.
 *
 * @param	{scopes.globals.MyType}		someParam
 *
 */
function test(someParam)
{
application.output(someParam.version);
}

If I use just “@param {MyType}” the type is not recognized.
If I use globals.MyType or scopes.globals.MyType it is recognized but when I use the object it doesn’t recognize it’s properties.

just “MyType” will never work in this situation
You have to scope it (its a type on that scope)
But it could be that that is not fully supported, i think what was fixes was if you define a typedef in a base form and then use it in a sub