Từ khóa `is` trong TypeScript làm gì?
Tôi đã gặp một số đoạn mã trông như thế này:
export function foo(arg: string): arg is MyType {
return ...
}
Tôi chưa thể tìm kiếm is trong cả tài liệu lẫn Google, đây là một từ khá phổ biến và xuất hiện trên hầu hết mọi trang.
Từ khóa đó hoạt động như thế nào trong bối cảnh đó?
Câu trả lời #1
Xem phần tham khảo về các hàm bảo vệ kiểu do người dùng định nghĩa để biết thêm thông tin.
function isString(test: any): test is string{
return typeof test === "string";
}
function example(foo: any){
if(isString(foo)){
console.log("it is a string" + foo);
console.log(foo.length); // string function
}
}
example("hello world");
Sử dụng bộ bảo vệ kiểu test is string ở định dạng trên (thay vì chỉ sử dụng boolean cho kiểu trả về), sau khi isString() được gọi, nếu hàm trả về true, TypeScript sẽ thu hẹp loại thành string trong bất kỳ khối nào được bảo vệ bởi lệnh gọi hàm này. Trình biên dịch sẽ coi foo là chuỗi trong kiểu được bảo vệ khối bên dưới (và CHỈ trong khối được bảo vệ bên dưới)
{
console.log("it is a string" + foo);
console.log(foo.length); // string function
}
Một bộ tiên đoán kiểu chỉ được sử dụng trong thời gian biên dịch. Tệp .js kết quả (thời gian chạy) sẽ không có gì khác biệt vì nó không xem xét KIỂU.
Tôi sẽ minh họa sự khác biệt trong bốn ví dụ dưới đây.
Ví dụ 1: mã ví dụ ở trên sẽ không có lỗi biên dịch cũng như lỗi khi chạy.
Ví dụ 2: đoạn mã ví dụ dưới đây sẽ gặp lỗi biên dịch (cũng như lỗi thời gian chạy) vì TypeScript đã thu hẹp kiểu thành string và kiểm tra rằng toExponential không thuộc phương thức của string.
function example(foo: any){
if(isString(foo)){
console.log("it is a string" + foo);
console.log(foo.length);
console.log(foo.toExponential(2));
}
}
Ví dụ 3: đoạn mã ví dụ dưới đây không có lỗi biên dịch nhưng sẽ có lỗi khi chạy vì TypeScript chỉ thu hẹp kiểu thành string trong khối được bảo vệ chứ không phải sau đó, do đó foo.toExponential sẽ không gây lỗi biên dịch (TypeScript không nghĩ nó là kiểu string). Tuy nhiên, khi chạy, string không có phương thức toExponential, vì vậy sẽ có lỗi khi chạy.
function example(foo: any){
if(isString(foo)){
console.log("it is a string" + foo);
console.log(foo.length);
}
console.log(foo.toExponential(2));
}
Ví dụ 4: nếu chúng ta không sử dụng test is string (predicate kiểu), TypeScript sẽ không thu hẹp kiểu trong khối được bảo vệ và đoạn mã ví dụ dưới đây sẽ không có lỗi biên dịch nhưng sẽ có lỗi khi chạy.
function isString(test: any): boolean{
return typeof test === "string";
}
function example(foo: any){
if(isString(foo)){
console.log("it is a string" + foo);
console.log(foo.length);
console.log(foo.toExponential(2));
}
}
Kết luận là test is string (kiểm tra kiểu) được sử dụng trong thời gian biên dịch để thông báo cho các nhà phát triển rằng mã có khả năng gặp lỗi vào thời gian chạy. Đối với JavaScript, các nhà phát triển sẽ không BIẾT lỗi đó trong thời gian biên dịch. Đây là lợi thế của việc sử dụng TypeScript.
Câu trả lời #2
Công dụng duy nhất mà tôi biết là ví dụ của bạn: chỉ định một «tiên đề loại» (arg is MyType) trong một Bộ Bảo Vệ Loại do người dùng định nghĩa
Xem Kiểm soát loại do người dùng định nghĩa trong tài liệu tham khảo này
Đây là một tham chiếu khác
