Repository: TypeScript
Issue: `@typedef {Function}` generates a type that can be read, but can't be applied
Labels: Suggestion,Domain: JSDoc,Experience Enhancement

### 🔎 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:

```js
/**
 * @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:

```txt
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

```js
"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.

```diff
/**
- * @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:

```diff
/**
- * @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!`;
}
```

```txt
JSDoc '@typedef' tag should either have a type annotation or be followed by '@property' or '@member' tags.
```