This error occurs when you try to import a type that exists in a library but is not explicitly exported in its declaration file. It typically happens with module resolution Node16/NodeNext or when types are marked as private.
This TypeScript error indicates that you're attempting to import or reference a type that exists within a library's type definition file (.d.ts) but hasn't been explicitly exported for external use. This commonly occurs when library authors intentionally keep certain types private or when using stricter module resolution strategies like "Node16" or "NodeNext" that respect package.json "exports" fields. TypeScript declaration files can contain types that are used internally but not meant to be part of the public API. When you try to access these non-exported types, TypeScript blocks the import to maintain proper encapsulation. This is especially common in third-party libraries where the maintainers control what types are exposed to consumers. The error became more prominent after TypeScript 3.9, which changed how exports from .d.ts files are handled, making type visibility more strict and aligned with JavaScript module semantics.
Examine the library's declaration file to see what's publicly available:
# Look at the declaration file in node_modules
cat node_modules/library-name/index.d.ts
# Or check @types package if applicable
cat node_modules/@types/library-name/index.d.tsLook for export statements to identify publicly available types. If the type you need isn't exported, it's intentionally private.
Extract the type from exported functions or values using TypeScript utility types:
import { someFunction, someValue } from 'library-name';
// Infer return type
type MyType = ReturnType<typeof someFunction>;
// Infer parameter type
type ParamType = Parameters<typeof someFunction>[0];
// Infer type from a value
type ValueType = typeof someValue;This approach lets you derive the type without requiring it to be explicitly exported.
If you need the exact type structure, recreate it in your own codebase:
// types/custom.d.ts
export interface MyCustomType {
// Mirror the structure from the library's source
id: string;
name: string;
// ... other properties
}Base this on the library's documentation or source code. This gives you type safety without relying on private exports.
If the error only appears with strict module resolution, consider adjusting tsconfig.json:
{
"compilerOptions": {
// Change from Node16/NodeNext to bundler or node
"moduleResolution": "bundler",
// Or use the classic node resolution
"moduleResolution": "node"
}
}Note: This is a workaround. Node16/NodeNext provides better alignment with modern Node.js module behavior.
Some libraries export types from different entry points:
// Instead of importing from the main entry
// import { InternalType } from 'library-name';
// Try importing from specific subpaths
import { InternalType } from 'library-name/types';
import { InternalType } from 'library-name/dist/types';Check the library's package.json "exports" field to see available paths.
If you have a legitimate use case for the type, open an issue with the library maintainers:
## Request: Export [TypeName] type
**Use case:** Describe why you need this type exported
**Current workaround:** Explain how you're working around it
**Impact:** How this affects type safety in your applicationMany maintainers will export types if there's clear community demand.
Declaration File Behavior Changes
TypeScript 3.9 changed how exports in .d.ts files are handled. Before 3.9, all types in declaration files were implicitly available. After 3.9, only explicitly exported types are accessible, aligning with JavaScript module semantics.
Package.json Exports and Type Visibility
With Node16/NodeNext module resolution, TypeScript respects the "exports" field in package.json. Even if a type exists in a .d.ts file, it won't be accessible unless the path is listed in exports:
{
"exports": {
".": "./dist/index.js",
"./types": "./dist/types.d.ts" // Makes types path accessible
}
}Ambient vs Module Declarations
Types declared in ambient declaration files (no imports/exports) behave differently from module declaration files (with imports/exports). In module .d.ts files, you must explicitly export types for them to be available.
Type-only Imports
When importing types that are exported, use type-only imports to ensure they're stripped during compilation:
import type { MyType } from 'library-name';This prevents runtime errors if the library only exports types without corresponding values.
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript