microsoft / microsoft/TypeScript
Improve type errors when applying a decorator to a member it does not support
Personne n'a encore pris cette issue.
- Langage dominant
- Go
- Étoiles
- 111k
- Forks
- 14.3k
- Merge moyen
- 1 j 19 h
- PR mergées (30 j)
- 117
Description
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 = '';
}
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.
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Utilisez l’exemple motivant et son lien TypeScript Playground comme reproduction de départ. Comparez les diagnostics actuels pour decorate1 et decorate2 sur des champs avec la formulation proposée pour accessor/field ; le travail est terminé lorsque les diagnostics identifient le type de membre non pris en charge et indiquent d’ajouter ou de supprimer le modificateur accessor lorsque cela s’applique.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- typescript
- Domaine
- compilers
- Type d'issue
- Fonctionnalité
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 35/100