TypeScript cơ bản – DOM, sự kiện và biểu mẫu trên trình duyệt
- 17-10-2026
- Toanngo92
- 0 Comments
Bạn đã dùng document và addEventListener trong JavaScript. Với TypeScript, trình biên dịch còn giúp phân biệt một phần tử thông thường với input hoặc form, đồng thời nhắc rằng phần tử có thể không tồn tại. Bài này dùng một biểu mẫu nhỏ để giải thích các kiểu DOM; đây là ví dụ minh họa, không phải dự án cuối khóa.
Mục lục
1. Chuẩn bị HTML và môi trường chạy
Giữ cấu hình ở bài tsconfig với lib chứa ES2022 và DOM. Tạo index.html ở thư mục gốc của dự án, cùng cấp package.json:
<!doctype html>
<html lang="vi">
<head><meta charset="UTF-8"><title>Biểu mẫu TypeScript</title></head>
<body>
<form id="name-form">
<label for="name">Tên của bạn</label>
<input id="name" name="name" required>
<button type="submit">Chào tôi</button>
</form>
<p id="message" role="status" aria-live="polite"></p>
<script type="module" src="./dist/main.js"></script>
</body>
</html>
File HTML tải JavaScript đã biên dịch trong dist, không tải main.ts. Script có type=”module” được thực thi sau khi HTML được phân tích, nên biểu mẫu đã có trong DOM. Ví dụ này phải mở qua một máy chủ HTTP cục bộ; không chạy bằng node dist/main.js vì Node.js không cung cấp document hay HTMLInputElement.
2. Kiểm tra sự tồn tại và loại phần tử
const form = document.getElementById("name-form");
const input = document.getElementById("name");
const message = document.getElementById("message");
if (!(form instanceof HTMLFormElement) ||
!(input instanceof HTMLInputElement) ||
!(message instanceof HTMLParagraphElement)) {
throw new Error("Không tìm thấy cấu trúc biểu mẫu cần thiết");
}
GetElementById trả về HTMLElement hoặc null. HTMLElement không đảm bảo có thuộc tính value như một input. Điều kiện instanceof vừa kiểm tra tại thời điểm chạy, vừa giúp TypeScript thu hẹp thành HTMLInputElement hoặc HTMLFormElement ở phần sau. Nếu HTML bị đổi sai id hoặc sai thẻ, chương trình báo rõ cấu trúc bị thiếu.
3. Đọc giá trị khi gửi biểu mẫu
form.addEventListener("submit", event => {
event.preventDefault();
const name = input.value.trim();
if (!name) {
message.textContent = "Vui lòng nhập tên.";
input.focus();
return;
}
message.textContent = "Chào " + name + "!";
});
PreventDefault ngăn hành vi gửi form mặc định. Giá trị của input.value là string; nếu cần số, bạn phải chuyển đổi rồi kiểm tra kết quả. Required xử lý trường rỗng ở mức HTML, còn trim giúp nhận ra chuỗi chỉ chứa khoảng trắng. TextContent hiển thị tên như văn bản, không biến nội dung người dùng nhập thành HTML.
4. Event target và currentTarget
input.addEventListener("input", event => {
const target = event.currentTarget;
if (target instanceof HTMLInputElement) {
target.setCustomValidity(
target.value.trim() ? "" : "Vui lòng nhập tên."
);
}
});
export {};
Target là nơi phát sinh sự kiện, có thể là một phần tử con khi sự kiện nổi bọt. CurrentTarget là đối tượng đang có listener được thực thi. Các thuộc tính này không mặc nhiên có kiểu HTMLInputElement và có thể liên quan đến null, nên kiểm tra trước khi dùng value. Với listener gắn trực tiếp lên input, giữ tham chiếu input đã kiểm tra cũng là một cách đơn giản.
5. Chạy ví dụ
Ghép lần lượt ba đoạn TypeScript ở trên vào src/main.ts, chỉ giữ một dòng export {} cuối file. Chạy npx tsc -p .. Sau khi biên dịch thành công, dùng máy chủ HTTP phát thư mục dự án rồi mở index.html. Bạn có thể dùng gói http-server với lệnh dưới đây; nếu trình quản lý gói hỏi cài gói, hãy đọc thông báo trước khi tiếp tục:
npx http-server . -c-1
Mở địa chỉ HTTP mà Terminal in ra và gửi biểu mẫu. Trình duyệt sẽ hiển thị lời chào; lỗi cấu trúc nếu có xuất hiện trong Console. Cờ -c-1 tắt cache của máy chủ cục bộ để dễ theo dõi thay đổi. Sau mỗi lần sửa TypeScript, cần biên dịch lại hoặc dùng chế độ –watch rồi tải lại trang.
6. Những khẳng định kiểu cần thận trọng
document.querySelector<HTMLInputElement>("#name") mô tả kiểu mong đợi, nhưng không xác minh thẻ thực tế là input. Tương tự, as HTMLInputElement và dấu ! không thay thế điều kiện kiểm tra. Khi cấu trúc HTML có thể thay đổi, instanceof giúp tránh khẳng định sai và làm lỗi dễ hiểu hơn.
Đọc thêm: TypeScript: DOM Manipulation.
Đọc thêm: http-server: hướng dẫn sử dụng.
Đọc tiếp trong loạt bài
Bài trước: TypeScript cơ bản – Module, import, export và tổ chức nhiều file
Bài tiếp theo: TypeScript cơ bản – Promise, async/await và kiểm tra dữ liệu API

