TypeScript error

TS8013: The ! operator in a .js file

  • Error TS8013
  • Tested with TypeScript 5.9

error TS8013: Non-null assertions can only be used in TypeScript files. is reported for a postfix ! such as document.getElementById("app")! in a .js file. In TypeScript the ! tells the checker a value is not null or undefined; JavaScript has no such operator.

Without it, the original problem returns: the value may be null (TS2531 or TS18047). Either prove it is there with a check, which also helps when the page changes, or state it with a cast.

At a glance

CodeTS8013
MessageNon-null assertions can only be used in TypeScript files.
TypeScript's categoryerror
Listed underJavaScript files only
Turned on by No option: every checked file reports it
In .js files Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file

The message is TypeScript's own text from its diagnostic messages file (Apache-2.0).

What it looks like

app.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: app.js(2,14): error TS8013: Non-null assertions can only be used in TypeScript files. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. app.js(2,14): error TS8013: Non-null assertions can only be used in TypeScript files. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. app.js(2,14): error TS8013: Non-null assertions can only be used in TypeScript files. checked 21 October 2026
const root = document.getElementById("app")!;error TS8013: Non-null assertions can only be used in TypeScript files.

root.append("Ready");
The ! operator in a .js file.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

What causes it

  • TypeScript code using ! was pasted into a .js file.

How to fix it

Check the value, or cast it

if (!root) throw new Error(...) narrows the variable and fails with a clear message if the element is ever missing. /** @type {HTMLElement} */ (document.querySelector("footer")) is the JSDoc version of the assertion, for elements the markup always has.

app.js TypeScript 5.9.3 TypeScript 5.9.3, run 21 October 2026: No errors. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. No errors. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. No errors. checked 21 October 2026
const root = document.getElementById("app");
if (!root) throw new Error("app.js: no #app element on this page");
root.append("Ready");

const footer = /** @type {HTMLElement} */ (document.querySelector("footer"));
footer.append("Loaded");
A check, or a cast that says the element is there.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Gotchas

  • ! before a value (!root) is ordinary JavaScript negation; only the postfix form is TypeScript.
  • In JSDoc types, a leading ! ({!HTMLElement}) is accepted but does not remove null, so it is no substitute; see the non-null assertions page.

Sources

Last reviewed 20 October 2026.