Skip to content

@typedef {Function} generates a type that can be read, but can't be applied #50274

Open
@coolaj86

Description

@coolaj86

🔎 Search Terms

callback typedef function alias semantic jsdoc tsc tsserver

🕗 Version & Regression Information

Always, up to Version 4.7.4

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about @callback

Summary

You should be able to create a typedef of a Function and use that type for any applicable function.

For example:

/**
 * @typedef {Function} PersonGreet
 * @param {String} name - other's name
 * @returns {String} - the greeting
 */

/** @type PersonGreet */
let greet = function (name) {
    return `Hello ${name}, my name is Rob the Robot!`;
}

However, this fails:

The type of a function declaration must match the function's signature.

Parameter 'name' implicitly has an 'any' type.

Complete Example

⏯ Playground Link

https://www.typescriptlang.org/play?filetype=js#code/EQVwzgpgBGAuBOBLAxrYBuAUJg9AKj0yjygAFYBPABwgBMIAzKAbwHkAjAKwlQF8oAChHhgA9gDsiJUlXiia8SiwDKCROIDm-cQEMAthCllZ84UuZCREgOLwIEWPw12HUnNnyFiZSjXpNmADEQcVRECX5LMXFbe1gjGR14fRYoiKhRWAALYQS7WBB4cTAVNU1eN2wAGwdBYWioAF4WXixcAgSqJJS2Lh5HKCpO7r1SpHLBgDpdAzyHQuLU+ojKtPFJ5DsdWGhmhhCwiSgACioAShYiKGua2EHl8SaWtuvrhWjp-V2pmYgX188Pmo0DWsVqeHcr3uVnWzjiT32oVg4UecIcx0yOXgF2YVyh13yCygAAMABIQKpVURQAAkzExwk+Bl4ABooHoKFBflBECU6e8JEyILwAITErBQ1rYKGEorQ6JYKWYPSiWggGqTCAADyookUJWaa3QQA

💻 Code

"use strict";

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

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

let 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 (other) {
        return `Hello ${other.name}, my name is ${person.name}!`;
    };

    return person;
};

module.exports = Person;

🙁 Actual behavior

In the example you can see that the checker doesn't apply the type PersonGreet to the function being assigned to person.greet.

The type declared with /** @typedef {Function} */ is parsed, but it can't be used to to type a compliant function directly (although it is somewhat usable as an export that other modules can understand the type in some contexts).

🙂 Expected behavior

A type generated with @typedef {Function} should be able to be applied to functions.

Workaround

There's no documentation for this, but it just so happens that if you use the @callback alias some extra machinery kicks in and you can type functions as you would have expected.

/**
- * @typedef {Function} PersonGreet
+ * @callback PersonGreet
 * @param {String} name - other's name
 * @returns {String} - the greeting
 */

/** @type PersonGreet */
let greet = function (name) {
    return `Hello ${name}, my name is Rob the Robot!`;
}

The problem is that @callback is usually incorrect and confusing:

  • all functions are functions
  • not all functions are callbacks
  • in fact, most functions are not callbacks

It's also possible to use TypeScript's proprietary arrow notation, but this generates other errors:

/**
- * @typedef {Function} PersonGreet
- * @param {String} name - other's name
- * @returns {String} - the greeting
+ * @typedef {(
+ *     other: Person
+ * ) => string} PersonGreet
 */

/** @type PersonGreet */
let greet = function (name) {
    return `Hello ${name}, my name is Rob the Robot!`;
}
JSDoc '@typedef' tag should either have a type annotation or be followed by '@property' or '@member' tags.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Domain: JSDocRelates to JSDoc parsing and type generationExperience EnhancementNoncontroversial enhancementsSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions