Jsdoc: Document class types/constructor types

Created on 19 Apr 2017  路  14Comments  路  Source: jsdoc/jsdoc

Right now I couldn't find a way to document that a function argument (a property, or anything really) is a class, or a constructor of a specific type.

Here's a condensed example of the problem:

class View {}

class SomeView extends View {}

/* *
* This is a factory function that instantiates a new view object 
* from the given View class and the given data.
* 
* @param {???} ViewClass a constructor/class that extends View
* @param {*} [data]
* @return View a new View instance
* */
function createView(ViewClass, data) {
  return new ViewClass(data)
}

var something = createView(SomeView, {});

How is it possible to tell that the type of ViewClass is a constructor/class and that it extends View?
What should go in the place of the question marks up there?

@param {View} thing this means that thing is a View instance, not a class
@param {Function<View>} thing this doesn't really mean that thing is a class that extends View
@param {typeof View} thing logically this is what we're looking for, but frankly I've never seen this one used before, not in the docs at least

Most helpful comment

This feature is highly missed. At my company, we use the convention Class.<A> to document constructors. This helps conveying the right information on the documentation, but is not recognized by tools.
Using the proposed typeof A works for IntelliJ (https://youtrack.jetbrains.com/issue/WEB-17325) but, unfortunately, causes _eslint_ to start failing doclet parsing...

All 14 comments

Is Function<View> currently the only one acceptable?

In VSCode, the assignment works (passing a constructor/class to a function expecting a Function<SuperClassType>) but the new is flagged with

[js] Cannot use 'new' with an expression whose type lacks a call or construct signature.

This is keeping me from using VSCode's static type checking :frowning_face:

Closure Compiler has a syntax for this: https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler#function-new-type

And TypeScript / VS Code even understands it.

I'm using jsdoc together with typescript since it let's me to write plain old javascript and do the typechecking against the jsdoc. The syntax:

@property {typeof SomeClass} SomeClass

seems to be working fine in that environment. In my case (and i think is a very common case) I'm documenting what a native library provides. The module is exporting an object which properties are classes so this was mandatory. Unfortunately this is not valid jsdoc code and I dont have a way to exclude some comments from the jsdoc parser :(

I think this is very very important

Have you tried the {function(new:SomeClass)} syntax from @thorn0 's link? Also, have you considered moving your module declarations out to a .d.ts file instead? I prefer documenting JS inline where possible, but in your case it might be more flexible to describe the native library in actual Typescript.

@thw0rted that would work only in the case that I do new SomeClass but not in the case I want to call static methods / static members (example below). What we really needs is typeof that BTW is supported by typescript although not documented. I'M WRITING A JSDOC PLUGIN TO CHANGE {typeof A} to {A} or to {Class<A>} so at least jsdoc won't fail but IMO this should be solved in jsdoc without plugins. FWI, I already implemented a plugin for preventing some comments to be parsed by jsdoc (https://github.com/cancerberoSgx/jsdoc-prevent-comment-parse-plugin) so I'm not blocked anymore, but I really want this information to be exported in the docs so I need this other plugin. Will let you know when done.

Example of static methods in which {function(new:SomeClass)} wont work:

/**@class */
class SomeClass(){

    /**
    * Extends the current component to generate a child one
    * @param {*} componentDefinition Any object with properties/methods that will be used to generate the Component that will be returned
    * @return {*}  
    * @static
    */
    static extend(componentDefinition) {
        return null
    }

}


.....

/**
@param {function(new:SomeClass)} Class
@return {*}
*/
function userCodeDONTwork(Class){
    return Class.extend({foo: 1})
}

/**
@param {typeof SomeClass} Class
@return {*}
*/
function userCodeWorks(Class){
    return Class.extend({foo: 1})
}

Done ! :) https://github.com/cancerberoSgx/jsdoc-typeof-plugin ... Now I can have types that refer classes, something very very basic that jsdoc should support.

This feature is highly missed. At my company, we use the convention Class.<A> to document constructors. This helps conveying the right information on the documentation, but is not recognized by tools.
Using the proposed typeof A works for IntelliJ (https://youtrack.jetbrains.com/issue/WEB-17325) but, unfortunately, causes _eslint_ to start failing doclet parsing...

@dcleao in my team we also started using Class but that won't work with typechecking validation in editors like webstorm, vscode, atom, etc. I think typeof is not a proprietary thing of webstorm or vscode but is more like a typescript / closure compiler "standard". IN the case of eslint, probably you should issue that team or ask them to support that as an enhancement .

+1 for typeof. In my case, I'm also interested in a future/Typescript-compatible way for pointing to an argument supporting a @callback signature or a specific method of an @interface (and I am not yet clear on whether Typescript supports this).

+1 for @param {typeof Foo} as per typescript & closer compiler. Not being able to specify a type of constructor / class and reference it's static methods is kind of a show-stopper for me right now. I'd love to see any solution that keeps both the closure compiler and JSDoc happy.

I think today TypeScript is the defacto "jsdoc" standard. Great part of jsdoc grammar is currently defined in the language itself and new jsdoc grammar for type-related things like this too.

Since is a formal grammar definition, IMO people will tend to move away from this project's grammar, particularly for type related semantics.

The TypeScript AST for

/**
 * @returns {typeof C}
 */
function f(){}

is something like this - sorry for the indentation

FunctionDeclaration JSDocComment JSDocReturnTag Identifier JSDocTypeExpression OpenBraceToken TypeQuery TypeOfKeyword <----- the same node kind than in actual typescript code Identifier <----- this is the name of a class or typedef CloseBraceToken FunctionKeyword

Since the objective of TypeScript is typecheck, they needed to create that syntax and used the same grammar that's already present in TypeScript for that. In other situations they use syntax already in TS for jsdocs, for example, generics - they don't support @template but the well known syntax {Array}.

On the other hand TS syntax don't support documentation-related semantic like @link, @example, etc.

My point is, for those who want typechecking and already have jsdocs comments, give TypeScript a try. No modifications are needed in a js project, can be done gradually mixing js and ts files, and compilation / Type errors can be configured pretty flexible. Also jsdocs itself ends up being simpler since in TS, jsdocs don't have types references or to explain what's you are documenting @class @method are no needed. That simplify the comments a lot.

I wonder if there are any plans in this project to catch up or support more of current TypeScript jsdocs syntax.

An interesting proiect could be parse js code using TypeScript compiler and generate a AST compatible with the syntax of this project (so I can use themes, etc to document TS/JS projects).

Any updates on this?

how to add restrictions like i am waiting for classes that extends certain other classes?
for example, my function accepts class parameter that extends B:
/** @param {any extends B} */
function foo(ClassName) {}

Was this page helpful?
0 / 5 - 0 ratings

Related issues

samskivert picture samskivert  路  13Comments

coryroloff picture coryroloff  路  18Comments

yagop picture yagop  路  13Comments

cowwoc picture cowwoc  路  29Comments

lukeapage picture lukeapage  路  34Comments