Áp dụng TypeScript vào trang web: truy xuất phần tử DOM có kiểu, xử lý sự kiện, gọi API bằng fetch và kiểm tra dữ liệu trả về để không tin mù quáng vào máy chủ.
- Lấy phần tử DOM với kiểu chính xác
- Gán kiểu cho sự kiện
- Viết hàm fetch tổng quát có kiểu
- Kiểm tra dữ liệu runtime bằng type guard hoặc thư viện schema
- HTMLElement
- Kiểu gốc của phần tử HTML; có kiểu con như HTMLInputElement.
- Non-null assertion (!)
- Khẳng định giá trị không null; nên hạn chế.
- Schema validation
- Kiểm tra cấu trúc dữ liệu khi chạy (ví dụ Zod, Valibot).
Khái niệm và lý thuyết
Thư viện chuẩn của TS (lib.dom.d.ts) mô tả toàn bộ API trình duyệt. document.querySelector("input") trả về HTMLInputElement | null: TS buộc bạn xử lý trường hợp không tìm thấy phần tử.
Dữ liệu từ mạng là ranh giới tin cậy: kiểu TypeScript không kiểm tra được lúc chạy. Cách đúng là coi kết quả response.json() là unknown, rồi kiểm tra trước khi gán kiểu. Thư viện schema cho phép viết một lần, vừa kiểm tra runtime vừa suy ra kiểu tĩnh.
DOM và sự kiện
const o = document.querySelector<HTMLInputElement>("#ten");
const nut = document.getElementById("gui") as HTMLButtonElement | null;
if (o && nut) {
nut.addEventListener("click", (e: MouseEvent) => {
e.preventDefault();
alert("Xin chào " + o.value.trim());
});
}
document.addEventListener("keydown", e => {
if (e.key === "Escape") console.log("Đóng"); // e tự là KeyboardEvent
});fetch có kiểu
interface NguoiDung { id: number; name: string; email: string }
function laNguoiDung(x: unknown): x is NguoiDung {
return typeof x === "object" && x !== null &&
typeof (x as any).id === "number" && typeof (x as any).name === "string";
}
async function layDanhSach(): Promise<NguoiDung[]> {
const res = await fetch("https://jsonplaceholder.typicode.com/users");
if (!res.ok) throw new Error("HTTP " + res.status);
const data: unknown = await res.json();
if (!Array.isArray(data) || !data.every(laNguoiDung))
throw new Error("Dữ liệu không đúng định dạng");
return data;
}Kiểm tra bằng schema (Zod)
import { z } from "zod";
const NguoiDung = z.object({ id: z.number(), name: z.string(), email: z.email() });
type NguoiDung = z.infer<typeof NguoiDung>; // kiểu suy ra từ schema
const ds = z.array(NguoiDung).parse(await res.json());Tạo ô input và danh sách <ul>. Khi gõ, lọc danh sách người dùng đã tải theo tên; hiển thị “Đang tải”, “Lỗi” bằng discriminated union ở Bài 5.
Dùng tham số kiểu của querySelector (querySelector<HTMLInputElement>) thay vì as để mã gọn và vẫn giữ kiểm tra null.
Toán tử ! (ví dụ getElementById("x")!) chỉ tắt cảnh báo; nếu phần tử không tồn tại, chương trình vẫn lỗi khi chạy.
- Tạo form đăng ký, đọc giá trị các input với kiểu chính xác.
- Viết hàm
getJSON<T>(url, kiemTra)tổng quát nhận type guard. - Hiển thị danh sách bài viết từ API jsonplaceholder.
- Thay type guard bằng schema Zod và so sánh độ dài mã.
- lib.dom cung cấp kiểu cho mọi API trình duyệt.
- Luôn xử lý trường hợp phần tử null.
- Dữ liệu mạng là unknown cho đến khi được kiểm tra.
- Schema validation hợp nhất kiểm tra runtime và kiểu tĩnh.