Lỗi gặp phải
Bạn đang refactor dở dang hoặc vừa pull một branch về và đột nhiên cả IDE đỏ rực:
Cannot find module './Component' or its corresponding type declarations. ts(2307)
Build thất bại. Không có gì compile được. Bạn kiểm tra file — nó vẫn ở đó. Bạn kiểm tra import — trông có vẻ đúng. Vậy vấn đề là gì?
TypeScript không thể phân giải module bạn đang import. File có thể tồn tại trên đĩa nhưng TypeScript không "thấy" được nó, hoặc các type bị thiếu hoàn toàn. Hãy loại trừ từng nguyên nhân một — có ít nhất năm tình huống khác nhau.
Chẩn đoán nhanh
Trước khi động vào bất cứ thứ gì, hãy xác định bạn đang gặp tình huống nào:
- File tồn tại nhưng TypeScript vẫn báo lỗi → vấn đề về đường dẫn hoặc extension
- Import một package npm → thiếu package
@types - Import file không phải TS (CSS, SVG, JSON) → thiếu khai báo module
- Vừa cài package → vấn đề về tsconfig hoặc node_modules
- Monorepo hoặc path aliases → cấu hình sai tsconfig paths
Cách sửa 1: Kiểm tra đường dẫn và extension của file
Lỗi kinh điển lúc 2 giờ sáng: đường dẫn sai. TypeScript phân biệt chữ hoa chữ thường trên Linux và macOS. Windows dễ tính hơn — điều này khiến các lỗi về chữ hoa/thường đặc biệt khó phát hiện khi code chạy tốt ở local nhưng lại bị lỗi trên CI.
// Sai — file thực ra là 'Button.tsx'
import Button from './button';
// Đúng
import Button from './Button';
Cũng cần kiểm tra xem có thiếu index của thư mục không:
// Nếu Component là một thư mục có chứa index.tsx
import Component from './Component'; // phân giải thành ./Component/index.tsx
import Component from './Component/index'; // khai báo rõ ràng
Với các file .tsx, hãy đảm bảo tsconfig của bạn có hỗ trợ JSX:
{
"compilerOptions": {
"jsx": "react-jsx"
}
}
Cách sửa 2: Thiếu package @types cho các module npm
Các package bên thứ ba như lodash hay express thường chỉ đi kèm JavaScript — không có type đi kèm. TypeScript không biết phải xử lý chúng thế nào.
Cannot find module 'lodash' or its corresponding type declarations. ts(2307)
Cài đặt package @types tương ứng:
npm install --save-dev @types/lodash
# hoặc
yarn add -D @types/lodash
# hoặc
pnpm add -D @types/lodash
Sau khi cài xong, hãy khởi động lại TypeScript server trong VS Code: Ctrl+Shift+P → TypeScript: Restart TS Server. Bỏ qua bước này là nguyên nhân của rất nhiều báo cáo "vẫn còn lỗi" đáng ngạc nhiên.
Để kiểm tra xem package types có tồn tại trước khi cài không:
npm search @types/your-package-name
Cách sửa 3: Tự khai báo module
Không có package @types? Bạn cần tự viết phần khai báo. Tạo file src/declarations.d.ts (hoặc src/global.d.ts) và thêm vào:
// Tối giản — báo cho TS biết "tin tôi đi, cái này tồn tại"
declare module 'some-untyped-package';
// Tốt hơn — thêm type nếu bạn biết cấu trúc
declare module 'some-untyped-package' {
export function doSomething(input: string): void;
export default function main(): void;
}
Các file tĩnh cũng cần khai báo. SVG, CSS module và ảnh đều cần khai báo module rõ ràng, nếu không TypeScript sẽ từ chối import chúng:
// src/declarations.d.ts
declare module '*.svg' {
const content: string;
export default content;
}
declare module '*.css' {
const styles: Record;
export default styles;
}
declare module '*.png' {
const src: string;
export default src;
}
Cách sửa 4: Sửa cấu hình module resolution trong tsconfig.json
Chiến lược phân giải sai khiến TypeScript tìm kiếm ở những chỗ không đúng. Điều này thường xảy ra với nhiều dự án đang chuyển sang ESM hoặc đổi bundler.
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true
}
}
Chọn moduleResolution nào:
"bundler"— dùng cho dự án Vite hoặc webpack (TypeScript 5.0+)"node16"hoặc"nodenext"— dùng cho Node.js với native ESM"node"— CommonJS cổ điển, các dự án cũ hơn
Hai cài đặt khác hay làm người dùng bối rối: esModuleInterop: true bắt buộc phải có khi dùng default import từ các package CommonJS. resolveJsonModule: true bắt buộc phải có khi dùng import data from './data.json'. Cũng cần xác minh rằng các file nguồn của bạn thực sự nằm trong phạm vi include hoặc rootDir.
Cách sửa 5: Path aliases không được phân giải
Path aliases như @/components/Button rất tiện lợi cho đến khi chúng âm thầm bị lỗi. Điểm mấu chốt: tsconfig paths chỉ ảnh hưởng đến việc kiểm tra type. Bundler của bạn hoàn toàn không biết về chúng trừ khi bạn cấu hình riêng.
Bước 1 — thêm vào tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
Bước 2 — cấu hình tương tự trong bundler. Với Vite:
// vite.config.ts
import { defineConfig } from 'vite';
import path from 'path';
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
});
Với webpack:
// webpack.config.js
module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
};
Cách sửa 6: Xóa node_modules và cài lại từ đầu
Các lần cài đặt bị lỗi và xung đột lockfile khiến node_modules rơi vào trạng thái hỏng một nửa. Package trông như đã được cài nhưng các file bị hỏng hoặc không khớp phiên bản. Đây là phương án cuối cùng — thô bạo, nhưng hiệu quả khoảng 80% trường hợp khi không có gì khác hợp lý.
rm -rf node_modules
rm package-lock.json # hoặc yarn.lock / pnpm-lock.yaml
npm install
Khởi động lại TS server sau đó.
Cách sửa 7: Kiểm tra file declarations.d.ts có được đưa vào tsconfig không
Đã tạo file .d.ts nhưng TypeScript vẫn bỏ qua nó? File cần phải nằm trong thư mục mà include của tsconfig đã bao gồm — hoặc được liệt kê rõ ràng:
{
"include": [
"src/**/*",
"src/declarations.d.ts"
]
}
Cách đơn giản nhất: chỉ cần đặt file .d.ts ở bất kỳ đâu bên trong src/ và tsconfig sẽ tự động nhận ra nó.
Xác nhận đã sửa xong
Chạy TypeScript compiler ở chế độ chỉ kiểm tra — không xuất file, chỉ kiểm tra lỗi type:
npx tsc --noEmit
# Không có output = không có lỗi
Trong VS Code, các gạch đỏ sẽ biến mất sau khi khởi động lại TS server. Vẫn còn hiển thị lỗi trong khi tsc --noEmit chạy sạch? Đó là vấn đề cache của VS Code, không phải lỗi thật. Hãy đóng workspace và mở lại.
Vẫn bí? Hãy theo dõi quá trình phân giải
Khi mọi cách đều thất bại, hãy bật ghi log phân giải chi tiết. Lệnh này sẽ hiển thị mọi đường dẫn TypeScript đã kiểm tra và chính xác nơi nó bỏ cuộc:
npx tsc --noEmit --traceResolution 2>&1 | grep -A5 "Module name '.*Component'"
Output khá nhiều, nhưng đây là công cụ debug dứt khoát cho ts(2307). Bạn sẽ thấy các dòng như Loading module as file/folder và File '.../Component.ts' does not exist — cho bạn biết chính xác TypeScript đang tìm kiếm trong thư mục nào và tại sao không tìm thấy gì.

