TypeScript error

TS8006: interface, enum or namespace in a .js file

  • Error TS8006
  • Tested with TypeScript 5.9

error TS8006: 'interface' declarations can only be used in TypeScript files. is reported for interface, enum and namespace (or module) declarations in a .js file. The {0} in the message is the keyword.

An interface only describes a shape, so in JavaScript it becomes a @typedef. An enum also creates a value at run time, so it becomes a real object: a frozen object for the values, plus @enum or a union of string literals for the type.

At a glance

CodeTS8006
Message'{0}' declarations 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); {0} is filled in by tsc for each error.

What it looks like

order.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: order.js(2,11): error TS8006: 'interface' declarations can only be used in TypeScript files. order.js(8,6): error TS8006: 'enum' declarations can only be used in TypeScript files. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. order.js(2,11): error TS8006: 'interface' declarations can only be used in TypeScript files. order.js(8,6): error TS8006: 'enum' declarations can only be used in TypeScript files. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. order.js(2,11): error TS8006: 'interface' declarations can only be used in TypeScript files. order.js(8,6): error TS8006: 'enum' declarations can only be used in TypeScript files. checked 21 October 2026
interface LineItem {error TS8006: 'interface' declarations can only be used in TypeScript files.
  sku: string;
  quantity: number;
}

enum Status {error TS8006: 'enum' declarations can only be used in TypeScript files.
  Pending,
  Shipped,
}

export const placed = Status.Pending;
interface and enum declarations 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 declarations were pasted into a .js file.

How to fix it

A @typedef for the shape, an object for the values

Write the interface as @typedef {object} LineItem with one @property per field. For the enum, export const Status = Object.freeze({ ... }) with /** @enum {string} */ gives a value you can import and a type for the members. A string literal union (@typedef {"pending" | "shipped"} Status) is often simpler when the values are only compared.

order.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
/**
 * @typedef {object} LineItem
 * @property {string} sku
 * @property {number} quantity
 */

/** @enum {string} */
export const Status = Object.freeze({
  Pending: "pending",
  Shipped: "shipped",
});

/** @type {LineItem} */
export const item = { sku: "TEE-01", quantity: 2 };

export const placed = Status.Pending;
A @typedef for the shape, and a frozen object with @enum for the values.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Gotchas

  • @enum types each member as the type in its tag (string here), not as the literal value; use a union @typedef when you need the exact strings checked.
  • A namespace in JavaScript is just an object; see the @namespace page for what the checker reads.

Sources

Last reviewed 20 October 2026.