TypeScript error

TS18042: A type imported with import in a .js file

  • Error TS18042
  • Tested with TypeScript 5.9

An import statement in a .js file is a real import: it runs when the module loads and needs a value at the other end. A @typedef or an interface from a .d.ts file is not a value, so import { LineItem } from "./types.js" is TS18042, and the message suggests the import() type form instead.

Since TypeScript 5.5, the @import tag says the same thing with the syntax of an import statement, and it disappears at run time.

At a glance

CodeTS18042
Message'{0}' is a type and cannot be imported in JavaScript files. Use '{1}' in a JSDoc type annotation.
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); {0} and {1} are filled in by tsc for each error.

What it looks like

cart.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: cart.js(2,10): error TS18042: 'LineItem' is a type and cannot be imported in JavaScript files. Use 'import("./types.js").LineItem' in a JSDoc type annotation. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. cart.js(2,10): error TS18042: 'LineItem' is a type and cannot be imported in JavaScript files. Use 'import("./types.js").LineItem' in a JSDoc type annotation. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. cart.js(2,10): error TS18042: 'LineItem' is a type and cannot be imported in JavaScript files. Use 'import("./types.js").LineItem' in a JSDoc type annotation. checked 21 October 2026
import { LineItem } from "./types.js";error TS18042: 'LineItem' is a type and cannot be imported in JavaScript files. Use 'import("./types.js").LineItem' in a JSDoc type annotation.

/** @param {LineItem[]} items */
export function count(items) {
  return items.reduce((n, item) => n + item.quantity, 0);
}
A type imported with import 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

  • Code moved from a .ts file, where import { Type } is fine because the import is erased.
  • An import of a name that used to be a value and is now only a type.

How to fix it

Use @import for types

/** @import { LineItem } from "./types.js" */ brings the type into scope for every JSDoc tag in the file. On TypeScript before 5.5, write import("./types.js").LineItem in the tags, or a @typedef that aliases it.

cart.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
/** @import { LineItem } from "./types.js" */

/** @param {LineItem[]} items */
export function count(items) {
  return items.reduce((n, item) => n + item.quantity, 0);
}
The same type brought in with @import.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["**/*.js"]
}

Gotchas

  • This site's tests found TS18042 with and without verbatimModuleSyntax: it is about JavaScript files, not about that option.
  • A name in @import that is never used is not checked at all, so a typo there stays hidden until a tag uses it.

Sources

Last reviewed 21 October 2026.