6

I'm trying to use a class defined in a library but I only receive an error as a result.

[LibraryProject]/library/model/Update.gs

class Update {
  constructor(obj = {}) {
    if(typeof obj == "string"){
      options = JSON.parse(obj);
    }
    Object.assign(this, obj);
  }

  text(){
    return (this.message && this.message.text)?this.message.text:''
  }
}

TASKS

✅ Create a new version of the project. (File > Manage versions...)

✅ Load this library in another project [Alias: CustomService] (Resources > Libraries...)

✅ Use functions of CustomService

❌ Use class of CustomService

If I try to use a Class

[NormalProject]/index.gs

function test  (){
  Logger.log(CustomService.libraryFunction())
  var update = new CustomService.Update("");
  Logger.log(update)
}

TypeError: CustomService.Update is not a constructor (línea 3, archivo "Code")

How can I instantiate an Object of this Class?

If I run...

In the image we can see the code and the error

Logger

We can see the two Logs, using function correctly and error when try to use Class constructir

TheMaster
  • 45,448
  • 6
  • 62
  • 85
raultm
  • 706
  • 6
  • 20

2 Answers2

9

As written in the official documentation,

Only the following properties in the script are available to library users:

  • enumerable global properties
    • function declarations,
    • variables created outside a function with var, and
    • properties explicitly set on the global object.

This would mean every property in the global this object are available to library users.

Before ES6, All declarations outside a function (and function declaration themselves) were properties of this global object. After ES6, There are two kinds of global records:

  • Object record- Same as ES5.

    • Function declarations
    • Function generators
    • Variable assignments
  • Declarative record - New

    • Everything else - let, const, class

Those in the declarative record are not accessible from the global "object", though they are globals themselves. Thus, the class declaration in the library is not accessible to library users. You could simply add a variable assignment to the class to add a property to the global object(outside any function):

var Update = class Update{/*your code here*/}

References:

TheMaster
  • 45,448
  • 6
  • 62
  • 85
  • the factory method solution is working, but I'll this approach to see if it works. Thanks – raultm Feb 29 '20 at 08:17
  • this works but we still can't see the documentation for that class or its methods, any solution that allow the documentation to pass through? – Legion Mar 23 '20 at 22:07
  • @Legion Documentation doesn't pass through. AFAIK, Only documentation that are supported are ``@param``and ``@returns``: Both of which are useless here. – TheMaster Mar 24 '20 at 02:53
4

Based on your tests, it appears that you cannot directly import a class from a GAS library. I'd recommend creating a factory method to instantiate the class instead.

Something along these lines:

// Library GAS project

/**
 * Foo class
 */
class Foo {
    constructor(params) {...}

    bar() {...}
}

/* globally accessible factory method */
function createFoo(fooParams) {
    return new Foo(fooParams);
} 

// Client GAS project

function test() {
    var foo = FooService.createFoo(fooParams);
    Logger.log(foo.bar());
}

TheAddonDepot
  • 8,408
  • 2
  • 20
  • 30