TypeScript - Kiểu Any: Đa năng như Dao pháp của Thụy Sĩ
Xin chào các ngôi sao lập trình tương lai! Hôm nay, chúng ta sẽ cùng tìm hiểu một trong những tính năng linh hoạt nhất (và đôi khi gây tranh cãi) của TypeScript: kiểu any
. Hãy chuẩn bị, vì chúng ta sắp bắt đầu một hành trình sẽ khiến bạn nói, "Any-thing is possible!" (Xin lỗi, tôi không thể résist một tí hài hước về kiểu 类型!)
Kiểu Any là gì?
Trước khi chúng ta bắt đầu, hãy tưởng tượng bạn đang tham gia một buổi tiệc buffet. Bạn mang theo một món ăn, nhưng bạn không biết ai mang gì khác. Đó chính là kiểu any
trong TypeScript - nó có thể giữ bất kỳ giá trị nào, giống như đĩa của bạn tại buổi tiệc buffet có thể giữ bất kỳ loại thức ăn nào!
Đại diện cho bất kỳ giá trị nào
Kiểu any
chính xác là như tên của nó - nó có thể đại diện cho bất kỳ giá trị nào trong TypeScript. Nó giống như một wildcard nói, "Hey TypeScript, tôi có thể là bất kỳ điều gì tôi muốn!"
Hãy xem một số ví dụ:
let myVariable: any = 42;
console.log(myVariable); // Output: 42
myVariable = "Hello, World!";
console.log(myVariable); // Output: Hello, World!
myVariable = true;
console.log(myVariable); // Output: true
myVariable = [1, 2, 3];
console.log(myVariable); // Output: [1, 2, 3]
Trong ví dụ này, chúng ta khai báo myVariable
với kiểu any
. Sau đó, chúng ta gán nó các giá trị khác nhau - một số, một chuỗi, một boolean, và một mảng. TypeScript không phàn nàn vì any
có thể là, à, bất kỳ điều gì!
Tham số hàm của kiểu any
Bây giờ, hãy tưởng tượng bạn đang tạo một hàm cần phải rất linh hoạt. Bạn muốn nó chấp nhận bất kỳ loại tham số nào. Đó là lúc any
trở nên hữu ích!
function printAnything(arg: any): void {
console.log(arg);
}
printAnything(42); // Output: 42
printAnything("TypeScript"); // Output: TypeScript
printAnything([1, 2, 3]); // Output: [1, 2, 3]
Trong ví dụ này, hàm printAnything
của chúng ta có thể chấp nhận bất kỳ loại đối số nào. Nó giống như một bảo vệ thân thiện tại câu lạc bộ cho phép tất cả mọi người vào!
Đối tượng của kiểu any
Đôi khi, bạn có thể muốn tạo một đối tượng có thể có các thuộc tính của bất kỳ kiểu nào. Hãy tạo một túi thần kỳ có thể giữ bất kỳ thứ gì:
let magicalBag: { [key: string]: any } = {};
magicalBag.book = "Harry Potter";
magicalBag.wand = { wood: "Holly", core: "Phoenix feather" };
magicalBag.spells = ["Expelliarmus", "Lumos", "Accio"];
console.log(magicalBag);
// Output:
// {
// book: "Harry Potter",
// wand: { wood: "Holly", core: "Phoenix feather" },
// spells: ["Expelliarmus", "Lumos", "Accio"]
// }
Ở đây, magicalBag
là một đối tượng có thể có bất kỳ số lượng thuộc tính nào, mỗi thuộc tính có thể là bất kỳ kiểu nào. Nó giống như túi của Mary Poppins - nó có thể giữ bất kỳ thứ gì!
Tại sao sử dụng kiểu any?
Bạn có thể tự hỏi, "Nếu TypeScript là về kiểu, tại sao chúng ta lại muốn sử dụng any
?" Câu hỏi tuyệt vời! Dưới đây là một vài tình huống mà any
có thể hữu ích:
- Khi làm việc với nội dung động (như dữ liệu từ một API)
- Khi dần chuyển đổi một dự án JavaScript sang TypeScript
- Khi làm việc với các thư viện thứ ba không có định nghĩa kiểu
Hãy xem một ví dụ về làm việc với nội dung động:
async function fetchUserData(userId: number): Promise<any> {
const response = await fetch(`https://api.example.com/users/${userId}`);
const userData = await response.json();
return userData; // Chúng ta không biết cấu trúc chính xác của userData, vì vậy chúng ta sử dụng 'any'
}
// Sử dụng
fetchUserData(123).then(user => {
console.log(user.name); // TypeScript sẽ không phàn nàn, ngay cả khi 'name' không tồn tại
});
Trong trường hợp này, chúng ta không chắc chắn về cấu trúc của dữ liệu chúng ta nhận được, vì vậy chúng ta sử dụng any
để nói với TypeScript, "Trust me, I know what I'm doing!"
Khẳng định kiểu
Đôi khi, bạn có thể biết nhiều hơn TypeScript về kiểu của một giá trị. Đó là lúc khẳng định kiểu ra vào. Nó giống như nói với TypeScript, "Tôi biết bạn nghĩ đây là any
, nhưng hãy tin tôi, nó thực sự là một kiểu cụ thể."
Dưới đây là cách bạn có thể sử dụng khẳng định kiểu:
let someValue: any = "Hello, TypeScript!";
let strLength: number = (someValue as string).length;
console.log(strLength); // Output: 20
Trong ví dụ này, chúng ta nói với TypeScript, "Hey, tôi biết someValue
là kiểu any
, nhưng tôi chắc chắn nó thực sự là một chuỗi. Vậy hãy để tôi sử dụng nó như một chuỗi."
Cẩn thận: Với quyền lực lớn đi kèm với trách nhiệm lớn
Mặc dù any
rất mạnh mẽ, nhưng nó nên được sử dụng tiết kiệm. Nhớ rằng, lợi ích chính của TypeScript là kiểm tra kiểu. Bằng cách sử dụng any
, bạn đang cơ bản nói với TypeScript tắt kiểm tra kiểu cho biến đó.
Dưới đây là một ví dụ về cách any
có thể dẫn đến lỗi thời gian chạy:
let num: any = "42";
console.log(num.toFixed(2)); // Điều này sẽ gây ra lỗi thời gian chạy!
TypeScript sẽ không phàn nàn về mã này, nhưng nó sẽ ném lỗi khi bạn chạy nó vì chuỗi không có phương thức toFixed
.
Any vs. Unknown: Lựa chọn an toàn hơn
TypeScript 3.0 đã giới thiệu kiểu unknown
, là một đối tác an toàn hơn của any
. Trong khi any
cho phép bạn làm bất kỳ điều gì mà không cần kiểm tra, unknown
bắt buộc bạn phải kiểm tra kiểu.
Hãy so sánh any
và unknown
:
let anyVar: any = 10;
let unknownVar: unknown = 10;
let s1: string = anyVar; // OK
let s2: string = unknownVar; // Lỗi: Kiểu 'unknown' không thể gán cho kiểu 'string'
// Chúng ta cần kiểm tra kiểu trước khi sử dụng unknownVar
if (typeof unknownVar === 'string') {
let s3: string = unknownVar; // OK
}
Như bạn có thể thấy, unknown
an toàn hơn vì nó bắt buộc bạn phải kiểm tra kiểu trước khi sử dụng.
Bảng phương thức
Dưới đây là bảng các phương thức phổ biến bạn có thể sử dụng với any
:
Phương thức | Mô tả | Ví dụ |
---|---|---|
typeof |
Trả về một chuỗi chỉ ra kiểu của toán tử không được đánh giá | typeof anyVar === 'string' |
instanceof |
Kiểm tra xem prototype property của một constructor có xuất hiện ở bất kỳ đâu trong prototype chain của một đối tượng | anyVar instanceof Array |
Khẳng định kiểu | Nói cho编译器 biết để treats một giá trị như một kiểu cụ thể | (anyVar as string).length |
Type guards | Các predicates định nghĩa bởi người dùng giúp thu hẹp kiểu của một biến | if (isString(anyVar)) { ... } |
Nhớ rằng, với any
, bạn có thể sử dụng bất kỳ phương thức nào tồn tại trong JavaScript, nhưng bạn sẽ mất đi lợi ích của kiểm tra kiểu của TypeScript.
Và thế là bạn đã cùng nhau khám phá thế giới của kiểu any
trong TypeScript. Nhớ rằng, trong khi any
có thể là một công cụ mạnh mẽ, nó giống như sức mạnh của siêu anh hùng - sử dụng nó khôn ngoan và có trách nhiệm. Chúc các bạn lập trình vui vẻ, và may mắn với các kiểu của bạn!
Credits: Image by storyset