This error occurs when using TypeScript's type-only import syntax in a JavaScript file or when file extensions don't match the content. The import type syntax, introduced in TypeScript 3.8, is only valid in .ts or .tsx files.
This error indicates that you're attempting to use TypeScript's type-only import syntax (import type) in a file that TypeScript doesn't recognize as a TypeScript file. The import type statement was introduced in TypeScript 3.8 to allow importing type information that gets completely erased at runtime, improving bundle size and build performance. The error typically appears in two scenarios: either you're using TypeScript syntax in a .js or .jsx file, or your file has the correct .ts/.tsx extension but VS Code or your build tool hasn't recognized it as TypeScript yet. In React projects, this is particularly common when migrating from JavaScript to TypeScript or when configuration issues prevent proper file recognition. Import type statements are compile-time only constructs that tell TypeScript "this import is only for type checking and should be removed from the final JavaScript output." This distinction is important for optimizing bundle sizes and clarifying developer intent.
Verify your file extension matches the content. For React components with JSX, use .tsx:
# Rename JavaScript file to TypeScript
mv MyComponent.jsx MyComponent.tsx
# For non-React files
mv utils.js utils.tsIn VS Code, you can right-click the file in the explorer and select "Rename" to change the extension.
After renaming files, VS Code may not immediately recognize the change. Reload the window:
1. Press Ctrl+Shift+P (or Cmd+Shift+P on Mac)
2. Type "Reload Window"
3. Select "Developer: Reload Window"
Alternatively, close and reopen VS Code to ensure all language services restart.
Ensure your TypeScript configuration includes the directory containing your files:
{
"include": [
"src/**/*",
"components/**/*"
],
"exclude": [
"node_modules",
"dist"
]
}If your files are outside the included paths, TypeScript won't process them.
If you're importing both types and runtime values, separate them or use inline type syntax:
// ❌ Incorrect - mixing types and values
import type { FC, useState } from 'react';
// ✅ Correct - separate imports
import type { FC } from 'react';
import { useState } from 'react';
// ✅ Also correct - inline type syntax
import { type FC, useState } from 'react';The inline syntax (available in TypeScript 4.5+) is often cleaner for mixed imports.
If TypeScript isn't installed in your project, add it:
# npm
npm install --save-dev typescript @types/react @types/react-dom
# yarn
yarn add -D typescript @types/react @types/react-dom
# pnpm
pnpm add -D typescript @types/react @types/react-domThen initialize a tsconfig.json if you don't have one:
npx tsc --initEnsure your build tool can process TypeScript files.
For Vite (already supports TypeScript):
// vite.config.js - no changes neededFor Webpack, ensure ts-loader or babel-loader with TypeScript preset:
module.exports = {
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
};For Next.js (supports TypeScript by default):
# Just add TypeScript files, Next.js auto-configuresIn VS Code, verify the language mode in the bottom-right corner shows "TypeScript React" or "TypeScript":
1. Click the language indicator in the status bar
2. Select "TypeScript React" for .tsx files
3. Select "TypeScript" for .ts files
If it shows "JavaScript" or "JavaScript React", the editor isn't treating it as TypeScript.
The import type syntax was introduced in TypeScript 3.8 as part of type-only imports and exports. It helps improve bundle sizes by ensuring type imports are completely erased during compilation, leaving no runtime remnant.
Starting with TypeScript 4.5, you can use inline type imports (import { type Foo, bar } from 'module') which is often cleaner than separate import type statements when you need both types and values from the same module.
If you're using the verbatimModuleSyntax option in tsconfig.json (available in TypeScript 5.0+), TypeScript enforces a strict distinction between type and value imports. This can help catch accidental mixing of types and runtime code but requires more explicit import statements.
In monorepo setups or projects with multiple tsconfig.json files, ensure all configurations properly include your source files. Path mapping in tsconfig.json (compilerOptions.paths) can also affect how TypeScript resolves imports.
For Create React App projects, note that CRA has built-in TypeScript support but requires files to have .tsx extensions. Ejecting or using CRACO may be necessary for advanced TypeScript configurations.
Some linters and formatters (like Biome or typescript-eslint) have rules that enforce or discourage import type usage. Check your linting configuration if you see conflicting guidance about when to use import type.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite