Giới thiệu
hocvietcode.com là website chia sẻ và cập nhật tin tức công nghệ, chia sẻ kiến thức, kỹ năng. Chúng tôi rất cảm ơn và mong muốn nhận được nhiều phản hồi để có thể phục vụ quý bạn đọc tốt hơn !
Liên hệ quảng cáo: [email protected]
Khi mọi thứ nằm trong main.ts, bạn khó biết phần nào là mô hình dữ liệu và phần nào là xử lý. Module cho phép mỗi file có phạm vi riêng và chỉ công khai những thành phần cần chia sẻ. Bài này dùng đúng package.json có type: module và tsconfig NodeNext ở bài chạy chương trình đầu tiên.
Mục lục
hoc-typescript/
package.json
tsconfig.json
src/
main.ts
models/
course.ts
services/
course-service.ts
dist/
Models chứa cấu trúc dữ liệu, services chứa hàm xử lý. Đây là cách chia đơn giản cho ví dụ, không phải quy tắc bắt buộc cho mọi dự án. Thư mục dist do TypeScript sinh ra, không phải nơi sửa mã nguồn.
Tạo src/models/course.ts:
export interface Course { id: number; title: string; free: boolean; }
Export trước interface cho phép file khác nhập tên Course. Nếu không export, khai báo vẫn thuộc phạm vi module đó. Interface được dùng khi kiểm tra kiểu và sẽ không tạo một object Course trong JavaScript đầu ra.
Tạo src/services/course-service.ts:
import type { Course } from "../models/course.js";
export function getFreeCourses(courses: readonly Course[]): Course[] {
return courses.filter(course => course.free);
}
Import type cho biết Course chỉ được dùng ở vị trí kiểu. Lệnh này bị loại khỏi JavaScript đầu ra, còn hàm getFreeCourses là giá trị thật và được export để chạy. Bạn không thể dùng import type để nhập một hàm rồi gọi hàm đó.
Điểm dễ nhầm là file nguồn tên course.ts nhưng đường dẫn import viết course.js. Với ES module chạy trực tiếp bằng Node.js và cấu hình NodeNext này, đường dẫn mô tả file JavaScript sẽ tồn tại sau biên dịch. TypeScript tìm được file nguồn tương ứng khi kiểm tra kiểu. Không đổi sang đuôi .ts hoặc bỏ đuôi theo thói quen của một bundler khác.
import type { Course } from "./models/course.js";
import { getFreeCourses } from "./services/course-service.js";
const courses: Course[] = [
{ id: 1, title: "TypeScript", free: true },
{ id: 2, title: "Đào tạo chuyên sâu", free: false }
];
console.log(getFreeCourses(courses).map(course => course.title));
npx tsc -p .
node dist/main.js
Kết quả là mảng chứa TypeScript. Trình biên dịch giữ cấu trúc thư mục tương ứng trong dist; main.js nhập getFreeCourses từ services/course-service.js. Nếu gặp lỗi không tìm thấy module, kiểm tra file nguồn, chữ hoa/thường, số cấp ../, đuôi .js và việc biên dịch đã thành công hay chưa.
Ví dụ sử dụng named export: tên được đặt trong dấu ngoặc nhọn khi import. Có thể đổi tên cục bộ bằng import { getFreeCourses as filterFree } from "./services/course-service.js";. Default export cho phép một giá trị mặc định của module được nhập mà không có dấu ngoặc nhọn. Cả hai đều hợp lệ; với nhiều hàm nhỏ, named export thường giúp nhìn rõ tên và tìm kiếm dễ hơn.
Node.js, trình duyệt thuần và công cụ đóng gói có quy tắc phân giải khác nhau. Vì vậy không sao chép một phần tsconfig của Vite hoặc framework vào ví dụ này rồi giữ nguyên các phần còn lại. Đường dẫn bí danh như @/models cũng cần sự phối hợp của công cụ chạy hoặc đóng gói; chỉ khai báo paths không tự viết lại đường dẫn JavaScript đầu ra.
Một file có import/export là module với phạm vi riêng. Tránh phụ thuộc vào biến toàn cục hoặc import qua lại thành vòng chỉ để lấy một giá trị. Khi hai module cần cùng một kiểu dữ liệu, đưa kiểu đó vào một file riêng như Course trong ví dụ sẽ làm quan hệ rõ hơn.
Đọc thêm: TypeScript: Modules.
Đọc thêm: Modules: Choosing Compiler Options.
Bài trước: TypeScript cơ bản – Generics và keyof: tái sử dụng mà vẫn giữ kiểu
Bài tiếp theo: TypeScript cơ bản – DOM, sự kiện và biểu mẫu trên trình duyệt
hocvietcode.com là website chia sẻ và cập nhật tin tức công nghệ, chia sẻ kiến thức, kỹ năng. Chúng tôi rất cảm ơn và mong muốn nhận được nhiều phản hồi để có thể phục vụ quý bạn đọc tốt hơn !
Liên hệ quảng cáo: [email protected]