This TypeScript warning appears when using the deprecated 'importsNotUsedAsValues' compiler option, which has been replaced by 'verbatimModuleSyntax' in TypeScript 5.0+. The fix involves updating your tsconfig.json to use the new option and adjusting your import statements to use explicit type-only imports.
The "importsNotUsedAsValues is deprecated" warning indicates you're using an outdated TypeScript compiler option that controls how imports are handled when they only reference types. This option was deprecated in TypeScript 5.0 in favor of the newer, more consistent 'verbatimModuleSyntax' option. The 'importsNotUsedAsValues' flag had three modes: 1. **remove** (default): Drop import statements that only reference types 2. **preserve**: Keep all import statements even if values/types are never used 3. **error**: Keep all imports but error when a value import is only used as a type The new 'verbatimModuleSyntax' provides clearer rules: imports/exports without 'type' modifier are preserved, while anything with 'type' modifier is dropped entirely. This makes the behavior more predictable and aligns better with modern JavaScript tooling. You'll see this warning when: - Your tsconfig.json still contains 'importsNotUsedAsValues' - You're using TypeScript 5.0 or newer - The compiler detects the deprecated option during compilation
Replace the deprecated 'importsNotUsedAsValues' option with 'verbatimModuleSyntax' in your tsconfig.json:
// OLD - deprecated
{
"compilerOptions": {
"importsNotUsedAsValues": "preserve"
}
}
// NEW - use verbatimModuleSyntax instead
{
"compilerOptions": {
"verbatimModuleSyntax": true
}
}If you were using 'importsNotUsedAsValues: "remove"' (the default), you can simply remove the option entirely, as TypeScript's default behavior is similar.
If you were using 'importsNotUsedAsValues: "error"', you should use 'verbatimModuleSyntax: true' and ensure your imports use explicit 'type' modifiers when needed.
With 'verbatimModuleSyntax', you need to be explicit about type-only imports. Update your code:
// OLD - TypeScript inferred this was type-only
import { User } from "./types";
const user: User = { name: "John" };
// NEW - Add explicit 'type' modifier
import { type User } from "./types";
const user: User = { name: "John" };
// OLD - Mixed import
import { User, getUser } from "./api";
// NEW - Separate value and type imports
import { getUser } from "./api";
import { type User } from "./api";
// OLD - Namespace import for types
import * as Types from "./types";
const user: Types.User = { name: "John" };
// NEW - Use 'import type' for namespace imports
import type * as Types from "./types";
const user: Types.User = { name: "John" };Key changes:
- Add 'type' modifier before type-only imports: import { type User }
- Use 'import type' for namespace imports of types: import type * as Types
- Keep regular imports for values: import { getUser }
When importing both values and types from the same module, separate them or use inline type modifiers:
// OPTION 1: Separate imports (clearer)
import { getUser, updateUser } from "./api";
import { type User, type UserPreferences } from "./api";
// OPTION 2: Inline type modifiers (more concise)
import { getUser, updateUser, type User, type UserPreferences } from "./api";
// OPTION 3: Namespace import with type modifier
import { getUser, updateUser } from "./api";
import type { User, UserPreferences } from "./api";
// WRONG - This will be removed at runtime with verbatimModuleSyntax
import { User, getUser } from "./api";
// User is a type, so the import will be dropped, breaking getUserThe rule is simple: if something is only used as a type, it needs a 'type' modifier or 'import type' statement.
The same rules apply to exports. Update type-only exports:
// OLD - TypeScript inferred this was type-only
export { User } from "./types";
// NEW - Add explicit 'type' modifier
export { type User } from "./types";
// OLD - Mixed export
export { User, createUser } from "./api";
// NEW - Separate or use inline type modifiers
export { createUser, type User } from "./api";
// OLD - Re-exporting types
export * from "./types";
// NEW - Use 'export type' for type-only re-exports
export type * from "./types";
// OR export specific types
export type { User, Product } from "./types";Important: With 'verbatimModuleSyntax', re-exporting everything (export * from "./types") will fail if the module contains both types and values. Use export type * for type-only modules.
After updating, test your build:
# Run TypeScript compiler
npx tsc --noEmit
# Or run your build command
npm run buildCommon issues to check:
1. Missing runtime imports: If a value import was incorrectly marked as type-only:
// WRONG - getUser is a value, not a type
import { type getUser } from "./api";
const user = getUser(); // Error: getUser is not defined at runtime
// CORRECT
import { getUser } from "./api";
const user = getUser();2. Third-party libraries: Some libraries may need @types updates:
npm install --save-dev @types/library-name3. Build tool integration: Ensure your bundler (webpack, Vite, etc.) handles the new import syntax correctly.
4. IDE support: Restart your TypeScript language server in VS Code (Cmd/Ctrl + Shift + P → "TypeScript: Restart TS Server").
Check other configuration files that might reference the deprecated option:
1. ESLint configuration:
// .eslintrc.json
{
"rules": {
"@typescript-eslint/consistent-type-imports": "error"
}
}2. Babel configuration (if using Babel with TypeScript):
// babel.config.json
{
"presets": [
["@babel/preset-typescript", {
"onlyRemoveTypeImports": true
}]
]
}3. Framework-specific configs (Next.js, Nuxt, etc.):
// next.config.js
module.exports = {
experimental: {
typedRoutes: true
}
};4. Monorepo configurations: Update all package.json and tsconfig.json files in your monorepo.
5. CI/CD pipelines: Ensure your build scripts use the updated TypeScript version and configuration.
### Migration Strategies for Large Codebases
For large projects, migrate incrementally:
1. Enable both options temporarily:
{
"compilerOptions": {
"verbatimModuleSyntax": true,
"importsNotUsedAsValues": "preserve"
}
}TypeScript will use 'verbatimModuleSyntax' but keep the old behavior as fallback.
2. Use ESLint to enforce type-only imports:
npm install --save-dev @typescript-eslint/eslint-plugin// .eslintrc.json
{
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/consistent-type-imports": [
"error",
{
"prefer": "type-imports",
"disallowTypeAnnotations": false
}
]
}
}3. Automated migration with codemods:
# Using jscodeshift
npx jscodeshift -t https://example.com/type-imports-codemod.ts src/### Understanding the Differences
importsNotUsedAsValues: "preserve":
- Keeps all imports in output JavaScript
- TypeScript removes type references at compile time
- Can lead to unused imports in bundle
verbatimModuleSyntax: true:
- Drops imports with 'type' modifier
- Preserves imports without 'type' modifier
- What you write is what you get in output
- More predictable for bundlers
### Compatibility with Build Tools
Webpack: Works natively with verbatimModuleSyntax
Vite/esbuild: Handle type-only imports correctly
Babel: Requires 'onlyRemoveTypeImports: true' in @babel/preset-typescript
SWC: Native support for TypeScript type-only imports
### TypeScript Version Support
- TypeScript 4.5+: Introduced inline 'type' modifiers
- TypeScript 5.0+: Introduced 'verbatimModuleSyntax', deprecated 'importsNotUsedAsValues'
- TypeScript 5.3+: Improved error messages for migration
### Common Pitfalls
1. Circular type dependencies: May need to restructure when using explicit type imports
2. Dynamic imports: import() expressions work the same
3. Conditional types: Type-only imports work with conditional types
4. Mapped types: No changes needed for type-only usage in mapped types
### Performance Implications
'verbatimModuleSyntax' can improve:
- Compilation speed: Clearer rules mean less analysis
- Bundle size: Unused type imports are removed
- Tree-shaking: Bundlers can better identify unused code
### Testing After Migration
Run comprehensive tests:
# Type checking
npx tsc --noEmit
# Unit tests
npm test
# Integration tests
npm run test:integration
# Build verification
npm run build && node dist/index.jsType parameter 'X' is not used in the function signature
How to fix "Type parameter not used in function signature" in TypeScript
Type parameter 'X' is defined but never used
How to fix "Type parameter is defined but never used" in TypeScript
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