Hàm là nơi kiểu phát huy tác dụng nhất. Bài này học cách khai báo tham số, giá trị trả về, tham số tùy chọn, overload và kiểu hàm.
- Gán kiểu tham số và giá trị trả về
- Dùng tham số tùy chọn, mặc định, rest
- Khai báo kiểu hàm và callback
- Viết overload và type guard
- Chữ ký hàm (signature)
- Mô tả kiểu tham số và kiểu trả về.
- Overload
- Nhiều chữ ký cho cùng một hàm.
- Type guard
- Hàm trả về
x is Tđể thu hẹp kiểu.
Khái niệm và lý thuyết
Mỗi hàm có một chữ ký: danh sách tham số kèm kiểu và kiểu trả về. TS kiểm tra lời gọi hàm có đúng số lượng, đúng kiểu đối số không. Kiểu trả về thường được suy luận, nhưng ghi tường minh giúp phát hiện sớm khi thân hàm trả sai.
Hàm trong JS là giá trị nên có kiểu hàm, ví dụ (a: number, b: number) => number. Kiểu tham số hàm là phản biến (contravariant): một hàm nhận kiểu rộng hơn có thể dùng ở chỗ cần hàm nhận kiểu hẹp hơn.
Tham số và giá trị trả về
function tong(a: number, b: number): number {
return a + b;
}
const nhan = (a: number, b = 2): number => a * b; // mặc định
function chao(ten: string, danhXung?: string) { // tùy chọn
return `Xin chào ${danhXung ?? ""} ${ten}`.trim();
}
function tongTatCa(...so: number[]): number { // rest
return so.reduce((s, x) => s + x, 0);
}Kiểu hàm và callback
type PhepToan = (a: number, b: number) => number;
const tru: PhepToan = (a, b) => a - b; // a, b tự có kiểu number
function apDung(ds: number[], f: (x: number) => number): number[] {
return ds.map(f);
}
apDung([1, 2, 3], x => x * x); // [1, 4, 9]Overload
function dinhDang(x: number): string;
function dinhDang(x: Date): string;
function dinhDang(x: number | Date): string {
return typeof x === "number" ? x.toLocaleString("vi-VN")
: x.toLocaleDateString("vi-VN");
}Chỉ các chữ ký phía trên được nhìn thấy từ bên ngoài; chữ ký cuối là phần cài đặt. Nếu union đủ diễn đạt, ưu tiên union thay vì overload.
Type guard và assertion function
interface Meo { keu(): void }
interface Cho { sua(): void }
function laMeo(x: Meo | Cho): x is Meo {
return "keu" in x;
}
function khangDinh(dk: unknown, msg: string): asserts dk {
if (!dk) throw new Error(msg);
}Với callback xử lý sự kiện, khai báo kiểu trả về void: TS cho phép truyền hàm trả về giá trị bất kỳ, nhưng bên gọi sẽ bỏ qua giá trị đó.
Tham số tùy chọn phải đứng sau tham số bắt buộc. Truy cập tham số tùy chọn khi chưa kiểm tra sẽ báo lỗi “possibly undefined” dưới chế độ strict.
- Viết hàm
tinhDiemTB(ds: number[]): numbertrả 0 nếu mảng rỗng. - Khai báo kiểu
BoLoc<T>là hàm nhận T trả boolean, dùng với filter. - Viết overload cho hàm
layGiaTrinhận id số hoặc mã chuỗi. - Viết type guard
laChuoi(x: unknown): x is string.
- Ghi kiểu tham số luôn; kiểu trả về nên ghi cho hàm công khai.
- Kiểu hàm mô tả callback.
- Overload khi các dạng gọi khác biệt rõ; còn lại dùng union.
- Type guard và asserts giúp thu hẹp kiểu an toàn.