microsoft / microsoft/TypeScript

Improve type errors when applying a decorator to a member it does not support

Aperta
#54,963 0 commenti 6 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Experience Enhancement Help Wanted Suggestion
Lingua principale
Go
Stelle
111k
Fork
14.4k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

Suggestion

🔍 Search Terms

standard decorators auto accessor member class error message

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

The typings for standard decorators allow them to indicate through their types what they may and may not be applied to. Currently TypeScript correctly errors in these cases, but the error messages are fairly abstract. This is likely to hit people migrating from the experimental decorators particularly hard, as many property decorators will become accessor decorators, requiring decorated properties to add the auto accessor annotation.

On the Lit team we've been seeing this issue as we prepare to vend standard versions of our decorators, see related PRs https://github.com/lit/lit/pull/3982, https://github.com/lit/lit/pull/4009

📃 Motivating Example

Consider code like:

declare function decorate1(target: unknown, context: ClassAccessorDecoratorContext): void;
declare function decorate2(target: ClassAccessorDecoratorTarget<unknown, unknown>, context: ClassAccessorDecoratorContext): void;

class Foo {
  @decorate1 prop1 = '';

  @decorate2 prop2 = '';
}

playground link

The mistake made with this code is that prop1 and prop2 are properties, but they need to be accessors, so the fix is to change Foo to read:

class Foo {
  @decorate1 accessor prop1 = '';

  @decorate2 accessor prop2 = '';
}

However the type errors are not particularly helpful in indicating this! decorate1 is squiggled with:

Unable to resolve signature of property decorator when called as an expression.
  Argument of type 'ClassFieldDecoratorContext<Foo, string> & { name: "prop1"; private: false; static: false; }' is not assignable to parameter of type 'ClassAccessorDecoratorContext<unknown, unknown>'.
    Types of property 'kind' are incompatible.
      Type '"field"' is not assignable to type '"accessor"'.

and decorate2 is squiggled with:

Unable to resolve signature of property decorator when called as an expression.
  Argument of type 'undefined' is not assignable to parameter of type 'ClassAccessorDecoratorTarget<unknown, unknown>'.

It would likely require some special casing, but when there is a type error when applying a decorator, I think it would be better to give an error closer to:

decorator1 prop1 = ''
~~~~~~~~~~

'accessor' decorator is not applicable to a 'field'.

In IDEs, for the specific case of applying an accessor decorator to a field, this is an opportunity to provide the fix of adding the accessor modifier to the declaration, or remove it when applying a field decorator to an accessor.

💻 Use Cases

The experimental decorators were frequently applied to fields to run logic when a field was set (e.g. change detection, reactive rendering, etc). With standard decorators, that use case can't be met by a field decorator, an accessor decorator must be used. Auto accessors are provided to make this easy and give a good developer experience, but they're likely to only be used for decorators, and developers will not be accustomed to using them.

When a developer is updating a code base to use standard decorators, or contributing to one that's already using them, they're likely to run into this issue and be quite confused until they can find a Q&A answer about this error message somewhere.

In the meantime, we'll be documenting this issue everywhere we talk about using standard decorators with Lit.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Usa l'esempio motivante e il relativo link a TypeScript Playground come riproduzione iniziale. Confronta le diagnosi attuali per decorate1 e decorate2 sui campi con la formulazione proposta per accessor/field; il lavoro è completato quando le diagnosi identificano il tipo di membro non supportato e indicano di aggiungere o rimuovere il modificatore accessor dove applicabile.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Funzionalità
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.