Repository: TypeScript
Issue: Function parameters are not inferable when defined via JSDoc using @type tag (with strict)
Labels: Help Wanted,Possible Improvement

### 🔎 Search Terms

`infer`
`@type`
`strict`
`JSDoc`
`Parameters`
`Function`

### 🕗 Version & Regression Information

- This is the behavior in every version I tried, and I reviewed the FAQ for entries about type inference.

I've pulled the latest version of this repository and made a test case in the "fourslash" section, which demonstrates the problem I see.
(I couldn't see how to do something like this in the playground, sorry. Commit is linked)

### ⏯ Playground Link

https://github.com/scottmcginness/TypeScript/commit/cda5366448cb994866517834e0c1ca78b10042cb

### 💻 Code

```javascript
// In file func.js
export function func(/** @type {string} */ param) {};
```

```ts
// In file use-it.js
import { func } from "./func.js";
type FuncParam = (typeof func) extends (...args: infer P) => any ? P : never;
//   ^ never, but expected [param: string]
```

In tsconfig.json:
```json
{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "noEmit": true,
    "strict": true
  }
}
```

(The above definition is obviously just `Parameters<T>`, but put in full for comparison with another example below)

### 🙁 Actual behavior

The type `FuncParam` resolved to `never` (i.e. it took the false branch of the ternary)

### 🙂 Expected behavior

The type `FuncParam` should be `[param: string]`, as given by the JSDoc `@type` tag

### Additional information about the issue

This seems like a bug because all other ways of specifying the `func` function with JSDoc or the `FuncParam` type seemed to work as expected:
  * Using the `@param` tag instead:
 ```js
/**
  * @param {string} param
  */
export function func(param) {};
```
yields `FuncParam` → `[param: string]`

  * Using a union with `undefined` works, but is not what I want for the definition of `func`:
```js
export function func(/** @type {string | undefined} */ param) {};
```
yields `FuncParam` → `[param?: string | undefined]`

  * Trying the conditional without `infer` works (but is not usable for the intended purpose):
 ```ts
import { func } from "./func.js";
type FuncIsAFunc = (typeof func) extends (...args: any) => any ? 'good' : never;
//   ^ 'good'
```

  * Pulling just the first parameter out also works (but obviously that's not how `Parameters<T>` works):
```ts
import { func } from "./func.js";
type FuncParam = (typeof func) extends (arg: infer A) => any ? A : never;
//   ^ string
```
---

This also only seemed to occur specifically with `strict: true`. I couldn't see this with any of the other `strict...` options (though I may have missed something here)

---

All other views on the function seems to show that it is happily a function with a string parameter. i.e. the tooltip hover over `func`, while inside `use-it.ts` shows:
```ts
(alias) function func(param: string): void
import func
```

---

The output I see from the [single test linked above](https://github.com/scottmcginness/TypeScript/commit/cda5366448cb994866517834e0c1ca78b10042cb) (using `hereby runtests --tests=jsDocInferredFunctionParameters`) is:
```
  1) fourslash tests
       tests/cases/fourslash/jsDocInferredFunctionParameters.ts
         fourslash test jsDocInferredFunctionParameters.ts runs correctly:

      AssertionError: At marker '': quick info text: expected 'type FuncParam = never' to equal 'type FuncParam = [param: string]'
      + expected - actual

      -type FuncParam = never
      +type FuncParam = [param: string]

      at _TestState.verifyQuickInfoString (src\harness\fourslashImpl.ts:1863:16)
      at Verify.quickInfoIs (src\harness\fourslashInterfaceImpl.ts:268:20)
      at eval (jsDocInferredFunctionParameters.js:13:8)
      at runCode (src\harness\fourslashImpl.ts:4618:9)
      at runFourSlashTestContent (src\harness\fourslashImpl.ts:4576:5)
      at runFourSlashTest (src\harness\fourslashImpl.ts:4559:5)
      at Context.<anonymous> (src\testRunner\fourslashRunner.ts:59:39)
      at processImmediate (node:internal/timers:476:21)
```

---

This also happens for arrow functions and class methods, e.g.
```js
// In func.js
export const func = (/** @type {string} */ param) => {};
export class Cls{
  method(/** @type {string} */ param) {}
}
```
with similar code as for `FuncParam`.