Abbiamo già buone risposte, ma penso che possiamo avvicinarsi a quello che si voleva in primo luogo:
Si può provare qualcosa di simile:
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 }]];
Rispetto alla risposta di NPE, è non hanno bisogno di oggetti wrapper attorno a stringhe e numeri.
Se si desidera un singolo numero o una stringa di essere un documento valido (che non è quello che hai chiesto, ma ciò che la risposta di NPE implica), si può provare questo:
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 ];
Aggiornamento:
L'utilizzo di un'interfaccia con la firma dell'indice anziché una matrice presenta lo svantaggio di perdere le informazioni sul tipo. Typescript non ti consentirà di chiamare metodi array come find, map o forEach. Esempio:
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);
}
Questo può essere risolto modificando la definizione di DocumentArray:
interface DocumentArray extends Array<ScalarDocument | DocumentArray> {}
Apparentemente, i riferimenti di tipo circolare sono consentiti: http: // stackoverflow.it/questions/24444436/circular-type-references-in-typescript – btk