I saw an old post that was never resolved and I am invested in it now.
Uncaught TypeError: Cannot read property ‘append’ of null in typescript
I tried reproducing it and I am also getting the error:
Uncaught TypeError: Cannot read property ‘append’ of null
export class UserForm { constructor(public parent: Element) {} template(): string { return ` <div> <h1> User Form</h1> <input/> <div> `; } render(): void { const templateElement = document.createElement('template'); templateElement.innerHTML = this.template(); console.log(this.parent); this.parent.append(templateElement.content); } }
this.parent
console logs null
for me as well. I thought perhaps it was because the DOM was not loading in time, but I tried this:
export class UserForm { // parent: Element; // constructor(parent: Element) { // this.parent = parent; // } constructor(public parent: Element) {} template(): string { return `<div> <h1>User Form</h1> <input /> </div>`; } render(): void { const templateElement = document.createElement("template"); templateElement.innerHTML = this.template(); window.addEventListener("DOMContentLoaded", (event) => { console.log("DOM fully loaded and parsed"); }); console.log(this.parent); this.parent.append(templateElement.content); } }
And I got the console log of DOM fully loaded and parsed
but this.parent
is still null
. If you do command + click for Element
you get that Element is the most general base class from which all objects in a Document inherit.
Does anyone have any idea what is going on here?
So far, I believe this has something to do with the fact that you do not always find an Element
in TypeScript, so you would get null
instead, but if this is the case, how do we resolve that?
Advertisement
Answer
So it appears that the key to solving this is the not null assertion operator or what in the world of English grammar we know as the exclamation point.
Basically, you tell TypeScript to relax and stop yelling at you because you know what you are doing. Root constant will definitely reference Element
. Otherwise, if the operator were to be omitted, root could refer to Element
or null
, if the element could not be found.
export class UserForm { constructor(public parent: Element) {} template(): string { return `<div> <h1>User Form</h1> <input /> </div>`; } render(): void { const templateElement = document.createElement("template"); templateElement.innerHTML = this.template(); console.log(this.parent); this.parent.append(templateElement.content); } }
Below would be the index.ts
file:
import { UserForm } from "./views/UserForm"; const root: Element = document.getElementById("root")!; const userForm = new UserForm(root); userForm.render();
Below is the index.html
:
<!DOCTYPE html> <html> <body> <div id="root"></div> <script src="./src/index.ts"></script> </body> </html>