typescript / expert
Snippet
Varianz-Annotationen mit in/out-Modifikatoren
TypeScript 4.7 führte explizite Varianz-Annotationen 'in' und 'out' für generische Typparameter ein. 'out T' markiert eine kovariante Position (der Typ erscheint nur in Ausgaben), 'in T' kennzeichnet Kontravarianz (nur Eingaben), und 'in out' erzwingt Invarianz. Diese Annotationen werden vom Compiler validiert: Wenn du einen Parameter mit 'out' markierst, ihn aber in einer Eingabeposition verwendest, meldet TypeScript einen Fehler. Über die Dokumentation hinaus beschleunigen sie Assignability-Checks, weil der Compiler die Varianz-Berechnung kurzschließen kann. Verwende sie bei Interfaces, deren generischer Parameter eine feste Rollenrichtung hat, um die Subtyping-Intention explizit zu machen.
snippet.ts
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface Producer<out T> {produce(): T;}interface Consumer<in T> {consume(value: T): void;}declare const animalProducer: Producer<{ name: string }>;// Covariant: a Producer<NarrowerOutput> flows into Producer<WiderOutput>const detailedProducer: Producer<{ name: string; age?: number }> = animalProducer;declare const stringConsumer: Consumer<string>;// Contravariant: a Consumer<WiderInput> flows into Consumer<NarrowerInput>const literalConsumer: Consumer<"hello"> = stringConsumer;
Erklärung
1
interface Producer<out T> {
'out' deklariert T als kovariant — Producer<Sub> ist Producer<Super> zuweisbar.
2
interface Consumer<in T> {
'in' deklariert T als kontravariant — Consumer<Super> ist Consumer<Sub> zuweisbar.
3
const detailedProducer: Producer<{ name: string; age?: number }> = animalProducer;
Funktioniert, weil Kovarianz erlaubt, dass ein Produzent einer engeren Form einen Produzenten einer weiteren Form erfüllt.
4
const literalConsumer: Consumer<"hello"> = stringConsumer;
Funktioniert, weil Kontravarianz erlaubt, dass ein Konsument des weiteren 'string' das engere Literal 'hello' akzeptiert.