Kiểu (type) trong TypeScript mô tả loại giá trị mà một biến có thể chứa. Bạn viết kiểu sau dấu hai chấm, let name: string, và trình biên dịch từ chối mọi đoạn code đặt sai loại giá trị vào đó. Các kiểu cơ bản là bảy kiểu nguyên thủy của JavaScript cùng object type cho mảng và đối tượng.
Các chú thích kiểu được kiểm tra lúc biên dịch rồi bị xóa đi. Chương trình được chạy là JavaScript thuần.
Các kiểu nguyên thủy
| Kiểu | Giá trị ví dụ | Ghi chú |
|---|---|---|
string | "hi", 'hi', `hi ${name}` | Văn bản. Cả ba kiểu dấu nháy đều cho cùng một kiểu. |
number | 42, 3.14, -0.5, NaN, Infinity | Mọi số, nguyên hay không. Không có int hay float. |
boolean | true, false | Chỉ hai giá trị này. |
bigint | 10n, BigInt(10) | Số nguyên với kích thước bất kỳ. Cần target ES2020 trở lên. |
symbol | Symbol("id") | Một giá trị duy nhất, chủ yếu dùng làm khóa của đối tượng. |
null | null | "Cố ý để trống". |
undefined | undefined | "Chưa được gán". Cũng là giá trị đọc ra từ thuộc tính không tồn tại. |
Tên kiểu viết thường. typeof lúc runtime trả về đúng những từ này cho hầu hết các kiểu, nên typeof x === "number" là cách kiểm tra kiểu nguyên thủy của một giá trị khi chương trình đang chạy.
Chú thích kiểu
Chú thích kiểu (type annotation) là : Type đặt sau biến, tham số hoặc danh sách tham số của hàm. Tham số là nơi chú thích kiểu quan trọng nhất, vì TypeScript không thể đoán nơi gọi sẽ truyền vào gì.
Khi biến được khởi tạo trên cùng một dòng, chú thích kiểu thường là thừa: let count = 10 đã có kiểu number. Các quy tắc để bỏ kiểu có ở trang suy luận kiểu.
Sai kiểu là lỗi biên dịch
Gán một giá trị sai kiểu và trình biên dịch dừng lại trước khi bất cứ thứ gì được chạy:
Trình biên dịch in ra:
index.ts(3,1): error TS2322: Type 'string' is not assignable to type 'number'.
Cách sửa là chuyển đổi giá trị, port = Number("3000"), hoặc đổi chú thích kiểu nếu biến thực sự cần chứa văn bản.
number: không có kiểu số nguyên
JavaScript lưu mọi số dưới dạng số thực dấu phẩy động 64 bit, nên TypeScript chỉ có một kiểu number. Số nguyên chính xác đến Number.MAX_SAFE_INTEGER (2 ** 53 - 1). Vượt quá mức đó, hãy dùng bigint.
bigint và number không trộn lẫn được: exact + 1 là lỗi biên dịch (TS2365: Operator '+' cannot be applied to types 'bigint' and '1'., trong đó '1' là kiểu literal của 1) và nếu có chạy thì cũng là TypeError lúc runtime. Hãy chuyển đổi tường minh một vế bằng BigInt(1) hoặc Number(exact), nhớ rằng Number làm tròn các giá trị vượt quá phạm vi an toàn.
Nếu bạn muốn một kiểu chỉ nhận số nguyên, TypeScript không biểu diễn được điều đó cho giá trị bất kỳ. Hãy kiểm tra bằng Number.isInteger ở chỗ giá trị đi vào chương trình.
boolean
boolean có đúng hai giá trị, true và false. Những giá trị chỉ là truthy (1, "yes") không phải boolean, nên hãy chuyển chúng thành boolean bằng Boolean(x) hoặc x !== 0.
null và undefined
Khi bật strict (mặc định từ TypeScript 6.0), null và undefined là các kiểu riêng và không thuộc string, number hay kiểu nào khác. Một biến có thể để trống phải nói rõ điều đó bằng union:
Đọc thuộc tính của một giá trị có thể là undefined là lỗi biên dịch cho đến khi bạn kiểm tra nó. Trang null và undefined nói về các phép kiểm tra, ?. và ??.
Sơ lược về mảng và đối tượng
Mọi thứ không phải kiểu nguyên thủy đều là object type. Ba dạng bạn gặp đầu tiên:
let tags: string[] = ["ts", "js"]; // array of strings
let point: { x: number; y: number } = { x: 1, y: 2 }; // object with two number properties
let greet: (name: string) => string = (n) => `hi ${n}`; // function type
Mỗi loại có trang riêng: mảng, tuple (mảng có độ dài cố định), object type và function type.
string, number, boolean và String, Number, Boolean
Các tên viết hoa là kiểu của đối tượng bao trong JavaScript (new String("x")), không phải của giá trị thông thường. Hãy chú thích kiểu bằng tên viết thường.
index.ts(3,7): error TS2322: Type 'String' is not assignable to type 'string'.
'string' is a primitive, but 'String' is a wrapper object. Prefer using 'string' when possible.
Đổi String thành string ở dòng đầu và khối code sẽ chạy. Điều tương tự áp dụng cho Number, Boolean, Symbol và BigInt. (Object là trường hợp khác: nó chấp nhận gần như mọi giá trị, kể cả kiểu nguyên thủy; xem phần object type.)
Các kiểu có sẵn khác
Vài kiểu khác cũng xuất hiện sớm. Mỗi kiểu có trang riêng.
| Kiểu | Ý nghĩa |
|---|---|
any | Tắt kiểm tra cho giá trị đó. Nên tránh. |
unknown | Giá trị bất kỳ, nhưng bạn phải kiểm tra trước khi dùng. |
void | Hàm không trả về giá trị hữu ích nào. |
never | Hoàn toàn không có giá trị: hàm luôn ném lỗi, hoặc một trường hợp không thể xảy ra. |
object | Mọi giá trị không phải kiểu nguyên thủy. |
"red" | "green" | Kiểu literal: chỉ đúng những giá trị này. |
Câu hỏi thường gặp
TypeScript có kiểu số nguyên không?
Không. number bao gồm cả số nguyên lẫn số thập phân, vì JavaScript lưu mọi số dưới dạng số thực 64 bit. Kiểm tra số nguyên lúc runtime bằng Number.isInteger(n), và dùng bigint (10n) khi bạn cần số nguyên lớn hơn Number.MAX_SAFE_INTEGER (2 ** 53 - 1) mà không mất độ chính xác.
string và String trong TypeScript khác nhau thế nào?
string là kiểu nguyên thủy, là kiểu của các chuỗi literal và template string. String là kiểu của đối tượng bao (wrapper) được tạo bởi new String("x"). Luôn chú thích kiểu bằng chữ thường string, number và boolean; gán một String cho một string là lỗi biên dịch (TS2322).
TypeScript có những kiểu nguyên thủy nào?
Bảy kiểu giống JavaScript: string, number, boolean, bigint, symbol, null và undefined. Mọi thứ còn lại (mảng, đối tượng, hàm, instance của lớp) đều là object type.
Khai báo biến có kiểu trong TypeScript thế nào?
Đặt dấu hai chấm và kiểu sau tên biến: let count: number = 0;. Với hàm, chú thích kiểu cho từng tham số và có thể cho cả kiểu trả về: function add(a: number, b: number): number. Khi biến được khởi tạo giá trị, thường bạn có thể bỏ chú thích và để TypeScript tự suy luận.
Kiểu của TypeScript có tồn tại lúc runtime không?
Không. Trình biên dịch kiểm tra kiểu rồi xóa chúng đi, nên JavaScript được chạy không có chú thích kiểu nào. Lúc runtime, bạn kiểm tra giá trị bằng các toán tử JavaScript như typeof, Array.isArray và instanceof.