Rekursiver Array-Typ TypeScript
Angenommen, ich habe den Typ type Atom=string | boolean | number. Ich möchte einen Typ für ein Array wie folgt definieren:
VerschachteltesArray=Atom | [a_0, a_1, ... , a_n], wobei jedes a_i ein Atom oder ein VerschachteltesArray ist.
Kann dies in TypeScript erreicht werden?
Antwort #1
Typ-Aliase können sich nicht selbst referenzieren, daher wird dieser naive Ansatz fehlschlagen:
type NestedArray = Atom | Array<NestedArray | Atom> //Type alias 'NestedArray' circularly references itself.
Schnittstellen können sich jedoch selbst referenzieren:
interface NestedArray extends Array<NestedArray | Atom> {
}
Und wir können auf oberster Ebene eine zusätzliche Union definieren, um den Wurzelfall zu behandeln:
type Atom = string | boolean | number
interface NestedArray extends Array<NestedArray | Atom> {
}
type AtomOrArray = Atom | NestedArray;
//Usage
let foo: AtomOrArray = [
"",
1,
[1, 2, ""]
]
let bar: AtomOrArray = ""
Antwort #2
TypeScript erlaubt jetzt, dass ein Typ sich selbst zirkulär referenziert, so wie dies:
type RArray = (string | RArray)[];
Und wenn Sie einen generischen Typ in einer rekursiven Funktion definieren möchten, können Sie interface ...<T> extends (T|...<T>)[] verwenden
interface RA<T> extends Array<T | RA<T>> { }
Erstellen Sie zum Beispiel eine Funktion, um die Summe rekursiv zu berechnen
function sum(arr: RA<number>) {
let res = 0;
arr.forEach((n) => {
if (Array.isArray(n)) {
res += sum(n);
} else {
res += n;
}
});
return res;
}
console.log(sum([1, 2, 3, [4, [5]], [[6]]]))
// output: 21
Aber diese Methode hat einige Nachteile, der Compiler kann den spezifischen Typ von n nicht kennen
arr.forEach((n) => {
if (Array.isArray(n)) { // typeof n: `number | RA<number>`
res += sum(n);
} else {
res += n;
}
});
