2014-10-06 10 views
23

sto cercando di creare un'istanza nuova HTMLDivElement a macchinaInstantiating nuova HTMLElement a macchina

var elem = new HTMLDivElement(); 

ma il browser getta

Uncaught TypeError: Illegal constructor. 

La soluzione sembra essere quella di utilizzare

var elem = document.createElement('div'); 

ma Trovo questo subottimale per vari motivi.

Perché non è possibile istanziare elementi DOM direttamente quando c'è una nuova parola chiaveper in nelle lib.d.ts?

declare var HTMLDivElement: { 
    prototype: HTMLDivElement; 
    new(): HTMLDivElement; 
} 

risposta

33

Si noti che l'errore che si ottiene qui è "Illegal constructor". Questo è diverso dall'errore "oggetto non è una funzione" che si otterrebbe se si dovesse scrivere new {}(), ad esempio.

Quindi, tecnicamente, HTMLDivElementfa avere un costruttore. È solo che questo particolare costruttore lancia un'eccezione piuttosto che creare un oggetto.

Normalmente lib.d.ts esclude solo tali firme inutili, ma TypeScript richiede che il lato destro dell'operatore instanceof disponga di un costruttore. In altre parole, è legale scrivere foo instanceof HTMLElement, ma non foo instanceof [] e la differenza è determinata dal fatto che HTMLElement ha un costruttore.

C'erano fondamentalmente tre scelte sul tavolo qui:

  1. rimuovere la firma costrutto dagli elementi DOM e rimuovere la restrizione operando di destra instanceof s'. Ciò è indesiderabile perché in realtà si preferisce rilevare errori in cui qualcuno scrive accidentalmente un codice come x instanceof foo anziché x instanceof Foo (dove foo è un'istanza di Foo).
  2. Rimuovere la firma del costrutto dagli elementi DOM, ma mantenere il controllo instanceof in posizione. Questo è male perché foo instanceof HTMLElement è una cosa molto ragionevole da scrivere.
  3. La situazione attuale, in cui i costruttori esistono ma è necessario sapere di non chiamarli.

Non è possibile costruire elementi DOM utilizzando i normali costruttori perché si suppone di passare attraverso document.createElement. Questo è fondamentalmente per motivi tecnici relativi al modo in cui i browser implementano questi oggetti.

+1

Incredibile spiegazione. Sarebbe possibile avere un commento in lib.d.ts che lo spieghi? O non vuoi inquinare lib.d.ts con commenti? –

+4

Avrebbe senso aggiungere un avvertimento o un errore da 'tsc' per il codice che richiama i costruttori su sottoclassi di' Elemento'? –

+0

Se estendi HTMLElement, ad esempio 'classe Thing estende HTMLElement', puoi usare new per creare un'istanza con' let t = new Thing() '. Quindi puoi aggiungerlo al DOM! – Kokodoko

3

Si è errata la sintassi del dattiloscritto con la sintassi C#.

basta sostituire

var elem = new HTMLDivElement(); 

larghezza

var elem = document.createElement('div'); 

o

var elem = <HTMLDivElement>(document.createElement('div')); 

(se avete bisogno di utilizzare gli attributi HTMLDivElement)

+2

Non c'è alcun problema con la sintassi, è un problema semantico. – yoniLavi