How to type hint Google Types in Google Scripts?
Asked Answered
L

3

6

I am trying to typehint a bunch of javascript in Google Script, and I have gotten as far as trying this:

/**
 *  Get (named) range given by name
 *
 *  @param {String} name 
 *  @return {Range}
 *
 */
function getRange(name) {
  return SpreadsheetApp.getActiveSpreadsheet().getRangeByName(name);
}

Which displays well and gives the same typehint as the builtin getRangeByName, however it does not actually work, i.e. the auto-complete script editor does not autocomplete when I type something like getRange("hello").get", like it should. Should I be name spacing the Range or am I doing something else wrong?

Lineate answered 27/10, 2020 at 12:34 Comment(6)
Use clasp with local ideLaura
I'm not sure if I understood, do you mean the Cntrl + Space autocomplete feature?Gordongordy
Off-note: is your name parameter really an instance of a String and not a string literal? When annotating with JSDoc, please, pay attention to what each type means, string and String do not mean the same thing.Ule
also: you will need this and yes, as TheMaster said, a local IDE and CLASP. You can't make the script editor magically know what the Range type isUle
@OlegValter thanks on the string note. I am a Python programmer by day, this is a side project. CLASP does seem the way forward, however surely there must be some way I can tell it what the Range is, because Google itself manages it? Surely if I matched what they write in their JSDoc for e.g. SpreadsheetApp methods, I could get the same behaviour?Lineate
@Lineate - good luck doing that :) Even if you did manage to reproduce it somehow, I don't think it is worth the time and effort as Google could change that at any time. Better use an IDE such as VS Code and install a @types/google-apps-script npm package - your life will never be the same again. That said, Google plans to migrate to a new online editor that uses the same engine (Monaco), so when they release it, any effort poured into trying to work around current limitations will go to waste.Ule
C
4

The current Google Apps Script IDE doesn't use local JSDOC to extend the autocomplete feature. Options:

  1. Create a Goole Apps Script library and attach it to your project
  2. Use another IDE

Regarding using another IDE at this time there is a tool called CLASP that helps to download/upload script which make it possible to use other IDEs.

Resources

Related

Other related

Categorize answered 27/10, 2020 at 19:36 Comment(5)
I am actually using a library as in the second link, so it is possible to get suggestions, but just not for types like Range?Lineate
@Lineate I'm sorry, I don't understand what you mean. Please bear in mind that JSDOC support in Google Apps Script IDE is limited.Categorize
So I have a library ScriptsLocal that I include in another script, and I can type hint a function in ScriptsLocal e.g. getRange(name) with name type string and its return type Sheet, and this will show up in the other script when I type ScriptsLocal.getRange. So the JSDOC is being picked up, but either my reference to Sheet is wrong (I tried things like SpreadsheetApp.Sheet) or I am doing something else wrong (using JSDOC wrong, as I said, I am not a JS programmer by trade).Lineate
Thanks. I have now done so: #64574338Lineate
This answer is incorrect nowadays - the Apps Script IDE does support JSDoc typing. See my answer below.Joacima
A
2

One can add type hints for a plain old javascript object by defining a class for it, and adding a comment above the constructor defining the parameter types

onEdit(e) (when a cell is edited) has an event, e as an input. Unfortunately, it there is no Event type in the script editor. We can fix that by defining an event class and adding a type hint for the parameter e like so:

class User {
   /**
    * @param {string} email
    * @param {string} nickname
    */
    constructor(email, nickname) {
    this.email = email;
    this.nickname = nickname;
  }
}

class Range {
   /**
    * @param {Number} columnEnd
    * @param {Number} columnStart
    * @param {Number} rowEnd
    * @param {Number} rowStart
    */
    constructor(columnEnd, columnStart, rowEnd, rowStart) {
    this.columnEnd = columnEnd;
    this.columnStart = columnStart;
    this.rowEnd = rowEnd;
    this.rowStart = rowStart;
  }
}

class Event {
   /**
    * @param {string} value
    * @param {User} user
    * @param {ScriptApp.AuthMode} authMode
    * @param {Range} range
    * @param {string} oldValue
    */
    constructor(value, user, authMode, range) {
    this.value = value;
    this.user = user;
    this.authMode = authMode;
    this.range = range;
  }
}

/**
* @param {Event} e
*/
function onEdit(e) {
  // now we have autocompletion on e properties
  SpreadsheetApp.getUi().alert(JSON.stringify(e));
  SpreadsheetApp.getUi().alert(e.user.email);
}
Auroraauroral answered 14/1, 2023 at 5:4 Comment(0)
J
1

Using a name qualified with SpreadsheetApp works for me.

/**
 *  Get (named) range given by name
 *
 *  @param {String} name 
 *  @return {SpreadsheetApp.Range}
 *
 */
function getRange(name) {
  return SpreadsheetApp.getActiveSpreadsheet().getRangeByName(name);
}

As evident in this screenshot:

enter image description here

Joacima answered 20/2 at 22:32 Comment(1)
I found the answer useful, but the screenshot was a bit confusing. I expected to see your getRange() being used, but it doesn't. I see now that it shows how SpreadsheetApp.Range appears as a type in other built-in functions. The text description was a bit confusing and it'd be useful to see an example of it working.Edgardo

© 2022 - 2024 — McMap. All rights reserved.