typescript - Implementera Iterable-gränssnittet med standard array-itererare
Jag har en Vector-klass som implementerar en Tuple, så här (förenklad kod, Tuple-gränssnittet är i princip bara en array utan metoder och med en fast storlek N):
interface Tuple<T, N extends number> extends ArrayLike<T>, Iterable<T> {
0: T
length: N
}
export class Vector<N extends number> implements Tuple<number, N> {
//Implementation
}
Nu vill jag göra min Vector itererbar. När jag skapar en variabel av typen Tuple är den redan itererbar, men Vector är uppenbarligen inte:
let t: Tuple<number,2> = [1,2]
for (const iterator of t) {...} //works
let v = new Vector([1,2])
for (const iterator of v) {....} //Type 'Vector<2>' must have a '[Symbol.iterator]()' method that returns an iterator.
Min fråga är: Hur implementerar jag "standard"-itereraren i min vektor, så att jag inte behöver skriva funktionerna igen? Kan jag på något sätt kopiera Itereraren från Tuples eller Arrays? Om detta inte är möjligt, vad är det bästa sättet att definiera min itererare? För tillfället har jag lagt till denna (generator) metod i min Vector-klass:
*[Symbol.iterator](): Iterator<number, any, undefined> {
for (let i = 0; i < this.length; i++) {
yield this[i]
}
}
Det fungerar, men jag är inte 100% säker på vad det faktiskt gör, vad returvärdet Iterator
Svar #1
Om du vill att din klass ska vara itererbar måste du definitivt på något sätt tillhandahålla en iterator. Men om du helt enkelt vill vidarebefordra iteration till en egenskap i din klass, då tror jag att du bara behöver implementera en getter som hämtar iteratorn från vad än du vill iterera över.
Till exempel något som:
export class Vector<N extends number> implements Tuple<number, N> {
constructor(public values: Tuple<number, N>) {}
get [Symbol.iterator]() {
return this.values[Symbol.iterator]
}
}
Och nu när du itererar det, får du faktiskt iteratorn från den interna egenskapen values, att iterera över.
Lekplats
Finns det ett sätt att göra detta utan att behålla 'values' som en objekt-egenskap (t.ex. genom att tilldela Symbol.iterator direkt i konstruktorn)?
Självklart. Som standard är iterator-egenskapen skrivskyddad, men om du deklarerar iterator-typen i klassen så säger du att den är skrivbar. Tilldela sedan iterator-egenskapen i konstruktorn.
class Vector {
[Symbol.iterator]: () => Iterator<number>
constructor(public values: number[]) {
this[Symbol.iterator] = this.values[Symbol.iterator]
}
}
Se lekplats
