Mamy już dobre odpowiedzi, ale myślę, że możemy zbliżyć się do tego, co chciał w pierwszej kolejności:
można spróbować coś takiego:
interface Document {
[index: number]: number | string | Document;
}
// compiles
const doc1: Document = [1, "one", [2, "two", [3, "three"]]];
// fails with "Index signatures are incompatible" which probably is what you want
const doc2: Document = [1, "one", [2, "two", { "three": 3 }]];
porównaniu do odpowiedzi NPE, w ty nie trzeba otaczać obiektów wokół łańcuchów i liczb.
Jeśli chcesz pojedynczą liczbę lub łańcuch być ważny dokument (który nie jest co pytasz, ale to, co sugeruje odpowiedź NPE), można spróbować to:
type ScalarDocument = number | string;
interface DocumentArray {
[index: number]: ScalarDocument | DocumentArray;
}
type Document = ScalarDocument | DocumentArray;
const doc1: Document = 1;
const doc2: Document = "one";
const doc3: Document = [ doc1, doc2 ];
Aktualizacja:
Używanie interfejsu z podpisem indeksu zamiast tablicy ma tę wadę, że traci informacje o typie. Maszynopis nie pozwala na wywoływanie metod tablic takich jak find, map lub forEach. Przykład:
type ScalarDocument = number | string;
interface DocumentArray {
[index: number]: ScalarDocument | DocumentArray;
}
type Document = ScalarDocument | DocumentArray;
const doc1: Document = 1;
const doc2: Document = "one";
const doc3: Document = [ doc1, doc2 ];
const doc = Math.random() < 0.5 ? doc1 : (Math.random() < 0.5 ? doc2 : doc3);
if (typeof doc === "number") {
doc - 1;
} else if (typeof doc === "string") {
doc.toUpperCase();
} else {
// fails with "Property 'map' does not exist on type 'DocumentArray'"
doc.map(d => d);
}
Problem ten można rozwiązać poprzez zmianę definicji DocumentArray:
interface DocumentArray extends Array<ScalarDocument | DocumentArray> {}
Najwyraźniej dozwolone są odwołania typu kołowego: http: // stackoverflow.com/questions/24444436/circular-type-references-in-typescript – btk