2016-03-02 9 views
6

Stiamo usando una semplice dichiarazione di funzione piuttosto dove la funzione accetta sia un singolo oggetto o una matrice di oggetti di un certo tipo.Funzione dattiloscritto che prende uno o una serie di oggetti

semplice dichiarazione è:

interface ISomeInterface { 
    name: string; 
} 

class SomeClass { 
    public names: ISomeInterface[] = []; 

    public addNames(names: ISomeInterface | ISomeInterface[]): void { 
     names = (!Array.isArray(names)) ? [names] : names; 
     this.names = this.names.concat(names); 
    }  
} 

Ma dattiloscritto getta "tipo non è cedibile" errore.

C'è un modo migliore per farlo? Ovviamente potremmo avere due funzioni separate, ma penso che gestire single vs multiple in questo modo sia abbastanza buono.

+1

Protip: invece di IsArray, nomi di uso = .concat [] (i nomi). 43% più veloce su cromo. –

risposta

8

È possibile rendere più facile

addNames(names: ISomeInterface | ISomeInterface[]): void { 
     this.names = this.names.concat(names); 
} 

Da MDN

The concat() method returns a new array comprised of the array on which it is called joined with the array(s) and/or value(s) provided as arguments.

+0

Un grande esempio di come sto sovra-ingegnerizzando qualcosa invece di leggere correttamente le specifiche ... grazie! Terrò l'altra risposta come accettata anche se ha un po 'di informazioni extra su TS che la gente sembra non sapere e ti dà più flessibilità su come passare i parametri – Tom

+0

In realtà, questo ancora compila in errore: 'Errore :(26, 46) TS2345: argomento di tipo 'ISomeInterface | ISomeInterface [] 'non è assegnabile al parametro di tipo' ISomeInterface '. Digitare 'ISomeInterface []' non è assegnabile al tipo 'ISomeInterface'. – Tom

+0

@Tom Ho aggiornato 'tsc' a' Versione 1.9.0-dev.20160302' ora funziona per me – isvforall

2

Il modo dattiloscritto ufficiale gestisce questo è con firme multiple funzioni, ad esempio:

addNames(names: ISomeInterface): void; 
addNames(names: ISomeInterface[]): void; 
addNames(names: any): void { 
    ... 
} 

È possibile visualizzare ulteriori informazioni nel official handbook here

+0

Sì, questo è quello che pensavo, ma se si chiama 'addNames (" Hello World ")' non genera alcun errore, quindi in pratica si potrebbe semplicemente usare la dichiarazione ': any' e sarebbe lo stesso ... – Tom

+0

Penso che devi solo convalidarlo da solo a quel punto. Non sono sicuro di come funzionerebbe, ma potresti provare a sostituire i nomi: any' con 'name ?: ISomeInterface, names ?: ISomeInterface []'. Questo dovrebbe impedire il passaggio di una stringa, ma ti permetterebbe di passare niente o entrambi. Quindi all'interno della funzione usa 'nomi || [nome] 'e sarebbe piuttosto semplice. – Marie

5

Si potrebbe anche utilizzare il parametro resto:

interface ISomeInterface { 
    name: string; 
} 

class SomeClass { 
    public names: ISomeInterface[] = []; // create an instance if applicable. 

    addNames(...names: ISomeInterface[]): void { 
     // the names argument will always be an array 
     this.names = this.names.concat(names); 
    } 
} 

Puoi chiamare come:

addNames(name1); // just pass one 
addNames(name1, name2, name3); // pass more comma separated 
addNames(...[name1, name2, name3]); // pass an array. 

Si noti che ho rimosso la parola chiave function, perché in caso contrario la parola chiave this all'interno del blocco del corpo potrebbe perdere l'ambito a seconda di chi la sta chiamando.

+0

Sì, bello, sapevo del resto param, ma quello che non sapevo è che si ricompone in params essendo sempre un array. grazie! – Tom

+0

Non sapevo che i parametri di riposo fossero stati compilati. Questa è una soluzione pulita! – Marie

+1

@Tom Vorrei anche suggerire di istanziare l'array in quanto impedirebbe di eseguire controlli "null" ovunque. 'nomi pubblici: ISomeInterface [] = [];' – Silvermind

0

penso che questo è ciò che si vuole

interface ISomeInterface { 
    name: string; 
} 

class SomeClass { 
    public names: ISomeInterface[]; 

    addNames(names: ISomeInterface | ISomeInterface[]): void { 
     names = (names instanceof Array) ? names : [names]; 
     this.names = this.names.concat(<ISomeInterface[]>names) 
    }  
} 

Si desidera utilizzare instanceOf, non IsArray.

+0

Scusa, non quello che stavo chiedendo e il tuo codice restituisce lo stesso errore – Tom

Problemi correlati