TypeScript cung cấp nhiều tính năng nâng cao về kiểu dữ liệu, giúp bạn tận dụng tối đa sức mạnh của hệ thống type. Bài viết này sẽ hướng dẫn về một số khái niệm quan trọng như kết hợp type, sử dụng các toán tử trên type và type guard.
Hệ thống type trong TypeScript không chỉ mạnh mẽ với việc giới thiệu nhiều kiểu dữ liệu mới mà còn với cách khai báo type đa dạng. TypeScript hỗ trợ nhiều toán tử hoạt động trên type như typeof
, keyof
, ?
, |
, &
, giúp bạn linh hoạt hóa quá trình xử lý kiểu dữ liệu.
Bằng cách sử dụng những toán tử này, bạn có thể tạo ra những type mới phức tạp dựa trên những type đã có, mang lại khả năng mở rộng và tái sử dụng code một cách hiệu quả.
Tham khảo:
Kết hợp type – intersection type
Các kiểu dữ liệu khác nhau có thể kết hợp nhau để tạo nên một type mới có các thuộc tính của các kiểu thành viên. Thể hiện trong khai báo type bằng dấu &
type sinhvien = { hoten: string; ngaysinh: string; } type hocbong = { tenhb: string; giatri: number; } type sinhviengioi = sinhvien & hocbong; let svg1: sinhviengioi = { hoten:"Nguyễn Văn Tèo", ngaysinh:'2001-04-27', tenhb:'Xuất sắc học kỳ 2', giatri:2000000 }; console.log(svg1);
Kiểu sinhviengioi sẽ gồm các thuộc tính từ type sinhvien và type hocbong.
Nếu 2 type có thuộc tính giống nhau thì phải cùng kiểu dữ liệu. Lúc này 2 thuộc tính được xem như 1. Còn nếu hai thuộc tính cùng tên nhưng khác kiểu dữ liệu sẽ bị báo lỗi nhé bồ.
type hocvien = { hoten: string; dienthoai: string; ghichu:string; } type khoahoc = { tenkhoa: string; khaigiang: string; ghichu:string } type danghoc = hocvien & khoahoc; let hv1: danghoc = { hoten:"Nguyễn Thị Gia Hu", dienthoai:'0918123456', tenkhoa:'18.3', khaigiang:'2023-01', ghichu:'học viên dễ thương' }; console.log(hv1);
Dùng toán tử typeof để chỉ định type cho biến
Trong TypeScript toán tử typeof để xác định kiểu dữ liệu của biến, từ đó có những tính toán thích hợp. Sau đây là một vài ví dụ sử dụng typeof.
Ví dụ 1: typeof dùng để xác định kiểu dữ liệu và tính toán
type T1 = number | string | boolean; let x:T1; x= 1; console.log( typeof x ) ; if ( typeof x =="number" ) x++; console.log (`x = `, x); x = "Tháng Giêng"; console.log(typeof x); x = true; console.log(typeof x);
Ví dụ 2: typeof dùng để xác định kiểu dữ liệu và tính toán
let str = "Hạnh phúc bây giờ"; let kq = true; console.log('Kiểu của biến str = ', typeof str);//string console.log( typeof kq =='boolean' ? "Đậu":"Rớt");
Toán tử typeof trong TypeScript cũng có thể dùng trong ngữ cảnh type, để khai báo biến theo type của các biến khác. Ví dụ:
let gia1:unknown; gia1 = 25000; console.log("Kiểu của gia1 = ", typeof gia1);//number let km1: typeof gia1; //number km1 = 1000;//ok let gia2:any; gia2 = "25000 đồng"; let km2: typeof gia2; //string km2 = "1000 đồng"; //ok console.log(`km1 = ${km1} , km2 = ${km2}`);
Dùng điều kiện trong định nghĩa type
Có thể diễn tả điều kiện với dấu ? trong định nghĩa type để chỉ định type linh động hơn. Cú pháp như sau:
type1 extends type2 ? TrueType : FalseType;
Khi type1 thực sự extends từ type2 thì kết quả được sử dụng là type ở trước dấu hai chấm (Truetype) ngược lại là FalseType
interface MàuSắc { rgb(): void;} interface MàuWeb extends MàuSắc { hsb(): void;} type MàuĐẹp = MàuWeb extends MàuSắc ? string:number; //string type GiaTriMau = BigInt extends MàuSắc ? string: number; //number let x:MàuĐẹp='darkblue'; let y:GiaTriMau=59;
Lấy type của thuộc tính – Indexed Access type
Có thể lấy type của một thuộc tính nào đó trên 1 type khác để xác lập type mới. Sử dụng cú pháp type[‘key’] như code sau:
enum KhoaPhong { CAPCUU, NGOAI, NOI} type BacSi = { tuoi: number; ten: string; khoa: KhoaPhong|string }; type TuoiBS = BacSi["tuoi"]; //number let x:TuoiBS = 36; //ok type KhoaBV = BacSi["khoa"]; let y:KhoaBV = KhoaPhong.CAPCUU; type T2 = BacSi[keyof BacSi]; // number| string | KhoaPhong let u:T2 = KhoaPhong.NOI;
Type guard trong TypeScript
Trong TypeScript, type guard đảm bảo rằng xử lý dữ liệu sẽ chính xác với loại của biến.
Tại sao chúng ta cần type guard? Bởi vì trong TypeScript, có những biến được định kiểu là any hoặc unknown. Có các lớp được mở rộng từ các lớp khác. Có các kiểu union kết hợp từ nhiều kiểu khác nhau. Vì vậy, type guard là cần thiết để xử lý dữ liệu mà không gặp lỗi.
Nếu không có type guard, bạn có thể gặp vấn đề khi sử dụng toán tử ++ cho một biến kiểu string chẳng hạn. Các type guard thường được sử dụng bao gồm instanceof, typeof, in và nhiều loại khác.
Sử dụng instanceof
Dùng instanceof để kiểm tra xem một đối tượng nào đó có phải là một thể hiện, tức instance của một class hay không
class sinhvien { hoten:string; ngaysinh:string; } class svgioi extends sinhvien { hocbong:number; } let sv1 = new sinhvien; let svg = new svgioi; let x:any = sv1; console.log( sv1 instanceof sinhvien ); //true console.log( sv1 instanceof svgioi ); //fasle console.log( svg instanceof sinhvien ); //true console.log( svg instanceof svgioi ); //true console.log( x instanceof svgioi ); //false console.log( x instanceof sinhvien ); //true
Sử dụng typeof
Đây là kiểu type guard thường dùng khi cần xác định kiểu dữ liệu của một biến. Toán tử typeof trả về các giá trị: boolean, string, bigint, symbol, undefined, function, number. Ngoài những cái này thì toán tử typeof sẽ trả về object.
Ví dụ sử dụng typeof để xác định kiểu của biến
Xác định xem biến thuộc kiểu nào để thực hiện tính toán thích hợp
type Thang = number | string ; let t:Thang; t = 0; if (typeof t =='number') t++; console.log(`t= `, t ); t = 'tháng giêng'; if (typeof t =='string') t = t.toUpperCase(); console.log(`t= `, t );
Dùng typeof để xác định xem 1 biến có phải là hàm không để chạy nó
Nếu typeof của 1 biến trả về là function thì biến đó là hàm. Lúc đó mới có thể gọi hàm để chạy.
let f:any; console.log(typeof f); //undefined f = "Mỗi ngày em hãy tìm một niềm vui"; console.log(typeof f); //string if (typeof f ==='function') console.log("Kết quả = " , f(1)); else console.log("f không phải hàm, không chạy nhé"); f = (x:number):number => (x+2)*3; console.log(typeof f); //function if (typeof f ==='function') console.log("Kết quả = " , f(1)); else console.log("f không phải hàm, không chạy nhé");
Typeof xác định kiểu biến là symbol, BigInt
let f:any; console.log(typeof f); //underfine f = Symbol('a'); console.log(typeof f); //symbol f = BigInt(562); //Số lớn không giới hạn giá trị Number.MAX_SAFE_INTEGER console.log(typeof f); //bigint
Sử dụng toán tử in xác định đối tượng chứa thuộc tính
Sử dụng toán tử in để xác định xem một đối tượng có chứa thuộc tính (attribute) hay không
interface màu { tênmàu:string; mãmàu:string; } let x:màu = { tênmàu:'Đỏ', mãmàu:'#ff0000' } console.log('id' in x); //false console.log('tênmàu' in x); //true
Cần tham khảo thêm hãy xem ở đây https://www.typescriptlang.org/docs/handbook/2/types-from-types.html
Việc sử dụng kiểu dữ liệu nâng cao trong TypeScript là một phần quan trọng, nhưng còn một khái niệm khác mà chúng ta nên tìm hiểu, đó là generic trong TypeScript. Hãy đọc tiếp để hiểu rõ hơn về chủ đề này trong bài viết dưới đây.
3 thoughts on “Type nâng cao trong TypeScript”