typescript - Implementer Iterable-grensesnittet med standard array-iteratør
Jeg har en Vector-klasse som implementerer en Tuple, slik som dette (forenklet kode, Tuple-grensesnittet er i utgangspunktet bare et array uten metoder og med en fast størrelse 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
}
Nå vil jeg gjøre vektoren min itererbar. Når jeg lager en variabel av typen Tuple, er den allerede itererbar, men vektoren er åpenbart ikke:
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.
Spørsmålet mitt er: Hvordan implementerer jeg den «standard» iteratoren i vektoren min, slik at jeg ikke må skrive funksjonene på nytt? Kan jeg på en eller annen måte kopiere Tuples eller Arrays iterator? Hvis dette ikke er mulig, hva er den beste måten å definere min iterator på? Foreløpig har jeg lagt til denne (generator) metoden i Vector-klassen min:
*[Symbol.iterator](): Iterator<number, any, undefined> {
for (let i = 0; i < this.length; i++) {
yield this[i]
}
}
Det fungerer, men jeg er ikke 100 % sikker på hva det egentlig gjør, hva returverdien Iterator
Svar #1
Hvis du vil at klassen din skal være itererbar, må du definitivt sørge for å gi en iterator på en eller annen måte. Men hvis du bare vil videreføre iterasjon til en egenskap av klassen din, tror jeg du bare trenger å implementere en getter som henter iteratoren fra det du vil iterere over.
For eksempel, noe sånt 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]
}
}
Og nå når du itererer det, får du faktisk iteratoren fra den interne egenskapen values, for å iterere over.
Lekeplass
Finnes det en måte å gjøre dette på uten å beholde 'values' som en objekt-egenskap (f.eks. ved å tildele Symbol.iterator direkte i konstruktøren)?
Selvfølgelig. Som standard er iterator-egenskapen skrivebeskyttet, men hvis du erklærer iterator-typen i klassen, sier du at den er skrivbar. Deretter tildeler du iterator-egenskapen i konstruktøren.
class Vector {
[Symbol.iterator]: () => Iterator<number>
constructor(public values: number[]) {
this[Symbol.iterator] = this.values[Symbol.iterator]
}
}
Se lekeplass
