microsoft / microsoft/TypeScript
Allow classes to implement unions of object types
Nessuno ha ancora preso questa issue.
- Lingua principale
- Go
- Stelle
- 111k
- Fork
- 14.3k
- Merge medio
- 1g 19h
- PR unite (30g)
- 117
Descrizione
🔍 Search Terms
class extends union type
✅ Viability Checklist
- 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 isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
⭐ Suggestion
Allow classes to extend unions of object types when the types in the union have the same set of properties.
The goal is to allow type-narrowing on class instances by checking a discriminant field.
📃 Motivating Example
I often have classes that represent data that can be in one of several states, and whose fields depend on that state.
An example is an object that is imported into a database with a long task. The app will write a record to the database to indication that it's currently being imported, and locking it from other writers.
We might model that with two interfaces: ImportingFoo, and ImportedFoo, discriminated by a status field:
type FooStates = ImportingFoo | ImportedFoo;
interface ImportingFoo {
status: 'importing';
value: undefined;
}
interface ImportedFoo {
status: 'imported';
value: string;
}
We want our class to implement this type to indicate what type value can be depending on the type of status:
class Foo implements FooStates {
status: 'importing' | 'imported' = 'importing';
value: undefined | string;
}
This currently gives a "A class can only implement an object type or intersection of object types with statically known members.(2422)" error.
If we could do that, we could use narrowing for the instance:
const getValue = (foo: Foo): string => {
if (foo.status === 'imported') {
return foo.value; // OK, because foo narrowed to a ImportedFoo
}
throw new Error('Invalid state');
}
💻 Use Cases
- What do you want to use this for?
- Classes that act as discriminated unions
- What shortcomings exist with current approaches?
- The class can't explicitly implement the union, narrowing doesn't automatically work
- What workarounds are you using in the meantime?
- Cast the instance to an intersection of the class and interface:
foo as Foo & ImportedFoo, but this is error prone as the cast will succeed in cases where it shouldn't.
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 tracciando la validazione di implements delle classi che produce la diagnostica 2422, quindi esamina come funziona il narrowing delle unioni discriminate per le istanze delle classi. Confronta gli esempi proposti FooStates e Foo e individua i test del compilatore che coprono l’implementazione delle classi e il narrowing. Il lavoro è completato quando le implementazioni valide delle unioni vengono accettate e il controllo mostrato di foo.status restringe correttamente foo.value senza modificare l’output JavaScript.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- 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