microsoft / microsoft/TypeScript
Suggestion: Reopen static and instance side of classes
Personne n'a encore pris cette issue.
- Langage dominant
- Go
- Étoiles
- 111k
- Forks
- 14.3k
- Merge moyen
- 2 j 4 h
- PR mergées (30 j)
- 132
Description
Summary
To support both the semantics of subclassing built-ins in ES6 and still allow authors to augment built-ins, we need a mechanism to reopen the static and instance sides of a class.
Current state
Today we can re-open interfaces, allowing authors to augment built-ins (for example, to support polyfills):
// in lib.d.ts
interface Array<T> { /*...*/ }
interface ArrayConstructor { /*...*/ }
declare var Array: ArrayConstructor;
// in polyfill.ts
interface Array<T> {
includes(value: T): Boolean;
}
interface ArrayConstructor {
of<T>(...items: T[]): Array<T>;
}
Array.prototype.includes = function (value: any) { return this.indexOf(value) != -1; }
Array.of = function<T> (...items: T[]) { return items; }
We can also re-open the static side of a class, in a limited fashion:
// initial declaration
class MyClass {
}
// re-open
module MyClass {
export var staticProperty = 1;
}
There are several issues with these approaches:
- You cannot use type defined by the
var/interfacepattern in theextendsclause of a class in TypeScript, meaning that "classes" defined using this pattern cannot be subclassed in ES6, which is an issue for built-ins. - While you can re-open the static side of a class using
module, you can only use non-keyword identifiers for property names. So you could not, for example, add a[Symbol.species]property to the class, or use decorators on these members. - There is no way to re-open the instance side of a class.
Proposal
I propose we add a new syntactic modifier for the class declaration that would indicate we are re-opening an existing class. For this example I am using the keyword partial, although the semantics here differ significantly than the same-named capability in C#:
// in lib.d.ts
declare class Array<T> {
}
// in polyfill.ts
partial class Array<T> {
static of<T>(...items: T[]) { return items; }
includes(value: T): boolean { return this.indexOf(value) != -1; }
}
// emit (ES5)
Array.of = function() {
var items = [];
for (var _i = 0; i < arguments.length; i++)
items[i] = arguments[i];
return items;
}
Array.prototype.includes = function(value) {
return this.indexOf(value) != -1;
}
Rules
- A
partialclass declaration must be preceded by a non-partialclass declaration in the same lexical scope. These should be the same rules that apply when merging a module with a class or function today. - A
partialclass declaration must have the same module visibility as the preceding non-partialclass declaration. - A
partialclass declaration must have the same generic type parameters (including constraints) as the non-partialclass declaration. - A
partialclass declaration cannot have anextendsclause, but may have animplementsclause. - A
partialclass declaration cannot have aconstructormember. - A
partialclass declaration cannot have members with the same name as existing members on a class.- Exception: ambient partial class declaration members can merge with other ambient partial class declaration members if they are compatible overloads, similar to interfaces.
- Non-static property declarations on a
partialclass declaration cannot have initializers. - A
partialclass declaration can have a class decorator. User code that executes in-between the initial class declaration and the partial declaration will be able to observe the class before decorators on thepartialclass are applied.- NOTE: We could choose to disallow class decorators on a
partialclass.
- NOTE: We could choose to disallow class decorators on a
Out of scope
- This proposal does not cover the case where built-in "classes" can often also be called as functions. This case is covered in #2959.
- This proposal does not cover the case where authors may have already extended the interface of a built in. This case is covered in #2961.
Previous discussions
This has also been discussed previously:
- #9 - Suggestion: Extension methods
- #563 - Partial classes
- https://typescript.codeplex.com/workitem/100
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
Commencez par lire les exemples de la proposition et les discussions précédentes référencées dans #9, #563 et l’élément de travail CodePlex lié. Le payload ne mentionne aucun fichier du dépôt, test ou point d’entrée ; pour considérer le travail comme terminé, il faudrait implémenter et valider les règles proposées pour les classes partielles, la fusion des éléments statiques et d’instance, les décorateurs et la sortie ES5.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- javascript, typescript
- Domaine
- compilers
- Type d'issue
- Fonctionnalité
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 25/100