· Jake Worth

Non-null assertion with getElementById


When I make a Vite TypeScript React app, it is created like this:

app.tsx
createRoot(document.getElementById('root')!).render(<App />);

As we learn and get more proficient at TypeScript, we may wonder: What’s going on with that exclamation mark(!)?

The ! is TypeScript is the non-null assertion operator. It’s a way of saying to the compiler: “I know that this is not null; don’t check it.”

Without it, you’ll see code like this on apps that developers have converted to TypeScript, checking for root with an if statement before trying to render the app.

app.tsx
const root = document.getElementById('root');
if (!root) {
throw new Error('Root element not found');
}
createRoot(root).render(<App />);

While I love a good explicit type check, in this context we control both index.html and app.tsx. Short of user error, root will always exist. And if it didn’t, the application wouldn’t start. The non-null assertion operator states explicitly this thing that we know is true.

One thing to keep in mind: the non-null assertion is compile-time only. TypeScript removes it from the emitted JavaScript, so this:

app.tsx
createRoot(document.getElementById('root')!).render(<App />);

is the same at runtime as calling createRoot on whatever getElementById returned, including null. The ! silences the type checker; it does not guard the call.

TypeScript docs- Non-null assertion operator