microsoft / microsoft/TypeScript

Function parameters are not inferable when defined via JSDoc using @type tag (with strict)

Ouverte
#58,580 5 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Domain: JSDoc Help Wanted Possible Improvement
Langage dominant
Go
Étoiles
111k
Forks
14.4k
Merge moyen
1 j 19 h
PR mergées (30 j)
117

Description

🔎 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
// In file func.js
export function func(/** @type {string} */ param) {};
// 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:

{
  "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:
/**
 * @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:
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):
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):
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:

(alias) function func(param: string): void
import func

The output I see from the single test linked above (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.

// In func.js
export const func = (/** @type {string} */ param) => {};
export class Cls{
  method(/** @type {string} */ param) {}
}

with similar code as for FuncParam.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par tests/cases/fourslash/jsDocInferredFunctionParameters.ts et exécutez-le avec la commande hereby indiquée dans l’issue afin de reproduire l’échec de quick-info. Suivez le comportement du TypeScript checker pour les paramètres JavaScript annotés avec JSDoc @type sous strict mode, y compris les fonctions fléchées et les méthodes de classe. C’est terminé lorsque le test signale [param: string] au lieu de never pour le tuple de paramètres inféré.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
javascript, typescript
Domaine
compilers
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Clairement spécifiée
Accessibilité débutants
38/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.