microsoft / microsoft/TypeScript
Suggestion: Reopen static and instance side of classes
Nessuno ha ancora preso questa issue.
- Lingua principale
- Go
- Stelle
- 111k
- Fork
- 14.3k
- Merge medio
- 2g 4h
- PR unite (30g)
- 132
Descrizione
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
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia leggendo gli esempi della proposta e le discussioni precedenti a cui si fa riferimento in #9, #563 e nell’elemento di lavoro CodePlex collegato. Il payload non indica file del repository, test o punti di ingresso; per considerare il lavoro completato sarebbe necessario implementare e convalidare le regole proposte per le classi parziali, l’unione degli elementi statici e di istanza, i decoratori e l’output ES5.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- javascript, typescript
- Ambito
- compilers
- Tipo di issue
- Funzionalità
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 25/100