error TS2694: Namespace '"/project/types"' has no exported member 'Prodcut'. is reported when a dotted type name, A.B, points into a module or namespace that has no B. In a JavaScript project that almost always means an import("./types.js").Name type in a JSDoc tag, where the name after the dot is not something the module exports.
The namespace in the message is the module, shown by its resolved path (tsc prints the full path; this site's examples live at /project). For packages it can be an internal name: Express's types, for instance, appear as e.
At a glance
| Code | TS2694 |
|---|---|
| Message | Namespace '{0}' has no exported member '{1}'. |
| TypeScript's category | error |
| Listed under | Unknown names and members |
| 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
/** @param {import("./types.js").Prodcut} product */error TS2694: Namespace '"/project/types"' has no exported member 'Prodcut'.
export function label(product) {
return product.name;
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} What causes it
- The type name after the dot is misspelled.
- The module does not export that type: it is declared under another name, or in another file of the package.
- With
moduleset topreserveoresnext, a file withoutimportorexportis a script, so its@typedefis global rather than an export; that case is reported as TS2306 (File ... is not a module.) instead. Undernodenextevery.jsfile is a module, so its top-level@typedefnames are always exports.
How to fix it
Use the name the module exports
Fix the spelling, or find the exported name: in the editor, completions after import("./types.js"). list what the module exports. In a .js module every @typedef at the top level is exported.
/** @param {import("./types.js").Product} product */
export function label(product) {
return product.name;
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Consider @import instead
Since TypeScript 5.5, /** @import { Product } from "./types.js" */ names the type once at the top of the file, and a misspelled name is reported on that line, where it is easier to see. See the @import page.
Gotchas
- The error is reported on the JSDoc comment, not on the code under it.
- In a project where files without
importorexportare scripts, anexport {}line makes a types-only file a module thatimport()types can point at.
Sources
- JSDoc Reference: Import types · TypeScript handbook
- TypeScript 5.5 release notes: the @import tag · TypeScript
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 20 October 2026.