Skip to content
Advertisement

How to type a JavaScript function with JSDoc + TypeScript?

I’m trying to use tsc with plain, Vanilla JS and I’m stumped on how to declare the type a function.

It seems like it should be this simple:

/** @type PersonGreet */
person.greet = function greet(other) {
  return `Hello ${other.name}, my name is ${person.name}!`;
};

Edit: /** @type PersonGreet */ is correct. The current behavior is a bug in tsc. The selected answer below gives valid workarounds.

Reduced Test Case

Ignore the fact that someone may want to refactor this into using classes or prototypes or some such – it serves well as a demonstration of the problem.

Repo: https://github.com/BeyondCodeBootcamp/hello-tsc

"use strict";

/**
 * @typedef {Object} Person
 * @property {String} name
 * @property {PersonGreet} greet
 */

/**
 * @typedef {Function} PersonGreet
 * @param {Person} other
 * @returns {String}
 */

let Person = {};

/**
 * Creates a person
 * @param {Object} p
 * @param {String} p.name
 * @returns {Person}
 */
Person.create = function (p) {
  let person = {};

  person.name = p.name;

  /////////////////////////////////////////////////////////////////////////////////
  //
  // error TS7006: Parameter 'other' implicitly has an 'any' type.  <======= WRONG!
  //
  /////////////////////////////////////////////////////////////////////////////////

  /** @type PersonGreet */
  person.greet = function greet(other) {
    return `Hello ${other.name}, my name is ${person.name}!`;
  };

  return person;
};

module.exports = Person;

Incorrectly Typed as “any”

When I run tsc to check it gives an error about an implicit any:

tsc -p jsconfig.json
person.js:28:33 - error TS7006: Parameter 'other' implicitly has an 'any' type.

28   person.greet = function greet(other) {
                                   ~~~~~


Found 1 error in person.js:28

What to do?

To me this seems like a bug in tsc… but this is JS 101 stuff, surely there must be a way to type a function?

What annotation do I need to use to declare the function’s type? Or can tsc / tsserver / typescript just not handle this kind of rudimentary use of JS?

Advertisement

Answer

Solution 1

You should use @callback instead of @function like so:

"use strict";

/**
 * @typedef {Object} Person
 * @property {String} name
 * @property {PersonGreet} greet
 */

/**
 * @callback PersonGreet
 * @param {Person} other
 * @returns {String}
 */

let Person = {};

/**
 * Creates a person
 * @param {Object} p
 * @param {String} p.name
 * @returns {Person}
 */
Person.create = function (p) {
  let person = {};

  person.name = p.name;

  /** @type {PersonGreet} */
  person.greet = function greet(other) {
    return `Hello ${other.name}, my name is ${person.name}!`;
  };

  return person;
};

module.exports = Person;

Solution 2

Or, declare a @typedef using typescript syntax like the following:

/**
 * @typedef {(other: Person) => string} PersonGreet
 */
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement