Làm cho việc loại bỏ lỗi Luồng cụ thể hơn
Chúng tôi đang cải thiện tính năng chặn lỗi Luồng để chúng không vô tình ẩn lỗi.
Trong năm tới, Flow đang có kế hoạch thực hiện nhiều thay đổi và cải tiến đối với hệ thống loại của mình . Tuy nhiên, một trong những hậu quả của việc này là bạn có thể cần thêm nhiều biện pháp ngăn chặn hơn vào mã của mình khi Flow trở nên tốt hơn trong việc tìm ra các vấn đề hiện có.
Đây có thể là một vấn đề vì việc ngăn chặn của Dòng chảy ảnh hưởng nhiều hơn đến lỗi ban đầu mà bạn định ngăn chặn. Điều này làm giảm khả năng bắt lỗi của Flow. Đây là kết quả của hai thuộc tính: Thứ nhất, ngăn chặn Luồng có thể nằm ở bất kỳ phần nào của lỗi loại và thứ hai, ngăn chặn Luồng có thể ngăn chặn bất kỳ loại lỗi loại nào . Để khắc phục những thiếu sót này, chúng tôi sẽ yêu cầu các biện pháp ngăn chặn được đặt tại vị trí trong mã của bạn nơi lỗi thực sự xảy ra và chúng bao gồm mã lỗi chỉ định loại lỗi bạn muốn ngăn chặn.
Để hiểu tất cả điều này có nghĩa là gì, hãy cùng tìm hiểu bản chất của các lỗi kiểu của Flow.
Lỗi kiểu là gì?
Khi Flow gặp sự cố trong khi kiểm tra mã của bạn, chẳng hạn như sự không tương thích giữa hai loại hoặc quyền truy cập thuộc tính không hợp lệ, nó sẽ tạo ra một lỗi báo cáo cho người dùng chính xác những gì sai với mã của họ. Những lỗi này có thể chứa nhiều thông tin khác nhau tùy thuộc vào các trường hợp cụ thể đã gây ra chúng, nhưng hai điều mà chúng tôi quan tâm nhất là loại lỗi và vị trí của lỗi.
Các loại của các lỗi mã hóa bản chất cụ thể của hành vi xấu mà dòng chảy phát hiện trong mã của bạn, cho dù đó là một cái gì đó đơn giản như đi qua quá nhiều đối số cho hàm, hoặc một cái gì đó phức tạp như lây lan một loại công đoàn. Thông tin này cho Flow biết chính xác loại thông tin nào sẽ hiển thị cho người dùng để giải thích chính xác nhất chính xác nơi bạn đã làm sai.
Vị trí lỗi chứa thông tin về vị trí lỗi trong mã của bạn. Có hai loại vị trí mà lỗi có thể chứa, vị trí chính (trong đó chỉ có thể có một) và vị trí phụ , trong số đó có thể có nhiều hoặc không có. Vị trí chính gần tương ứng với vị trí trong mã của bạn nơi lỗi thực sự xảy ra, trong khi các vị trí phụ mang thông tin về các vị trí xác định của các loại và giá trị liên quan đến lỗi. Ví dụ:
function foo(x : number) : void {}
foo("hello");
/* error */
foo("hello");
^ Cannot call `foo` with `"hello"` bound to `x` because string [1] is incompatible with number [2].
References:
2: foo("hello");
^ [1]
1: function foo(x : number) : void {}
^ [2]
function foo(x : number) : void {}
let y : string = "hello";
foo(y);
/* error */
foo(y);
^ Cannot call `foo` with `y` bound to `x` because string [1] is incompatible with number [2].
References:
2: let y : string = "hello";
^ [1]
1: function foo(x : number) : void {}
^ [2]
Vì vậy, có gì sai với sự đàn áp?
Chà, bởi vì việc triệt tiêu có thể được áp dụng cho cả vị trí chính và phụ, nên việc đặt //$FlowFixMe
nhận xét lên trên định nghĩa của foo
sẽ loại bỏ các lỗi trong cả hai ví dụ trên. Vì nó foo
xuất hiện như một vị trí phụ trong mọi lỗi sử dụng nó, điều đó có nghĩa là bất kỳ việc sử dụng foo
nào dẫn đến lỗi sẽ bị loại bỏ bởi một sự triệt tiêu này, ở bất kỳ nơi nào mà nó có thể xảy ra. Bạn có thể gọi foo
với bất kỳ loại đối số nào và Flow sẽ không hiển thị bất kỳ lỗi hoặc cảnh báo nào cho bạn về bất kỳ điều nào trong số này. Điều này làm suy giảm lòng tin của người dùng trong việc kiểm tra kiểu của Flow và cho phép các lỗi mà nó có thể đã mắc phải để đưa vào sản xuất.
Ngoài ra, việc ngăn chặn của Dòng chảy ảnh hưởng đến tất cả các loại lỗi, miễn là chúng chứa một vị trí mà việc ngăn chặn bao gồm. Điều này có nghĩa là nhiều lỗi thuộc các loại khác nhau có thể được loại bỏ bằng một lần triệt tiêu. Để thấy mối nguy hiểm trong việc này, hãy xem xét ví dụ sau:
// library file lib.js
function foo(x : number) : void {}
// impl file
const {foo} = require("lib.js");
let y : string = "hello";
// $FlowFixMe
foo(y);
Chúng ta sẽ làm gì về điều này?
Để giải quyết vấn đề này, chúng tôi sẽ thực hiện các thay đổi sau:
- Thực thi các vị trí chính. Chúng tôi sẽ thay đổi hành vi đàn áp để ngăn chặn chỉ áp dụng cho các lỗi khi được đặt tại vị trí chính của chúng. Ví dụ: thay vì cho phép bạn loại bỏ một cuộc gọi không hợp lệ theo định nghĩa của hàm, bây giờ chúng tôi sẽ yêu cầu việc loại bỏ đó phải được đặt tại chính trang web cuộc gọi. Bằng cách này, Flow vẫn có thể cảnh báo bạn về các lệnh gọi hàm có thể không hợp lệ khác.
- Thêm mã lỗi. Chúng tôi cũng sẽ thêm các mã lỗi vào các phần mềm ngăn chặn của mình để chúng chỉ loại bỏ các lỗi thuộc loại được chỉ định. Điều này sẽ ngăn chặn việc triệt tiêu bất ngờ loại lỗi bạn không mong đợi gặp phải.
- Chuẩn hóa cú pháp ngăn chặn. Trước đây, cú pháp có thể chấp nhận được để ngăn chặn lỗi có thể được định cấu hình theo cách thủ công trong
.flowconfig
cho một dự án nhất định, cho phép cú pháp triệt tiêu không nhất quán giữa các dự án. Là một phần của những thay đổi ở trên, chúng tôi cũng sẽ chuẩn hóa cú pháp ngăn chặn; chỉ hỗ trợ$FlowFixMe[incompatible-type]
hoặc$FlowExpectedError[incompatible-type]
các định dạng.
Giới thiệu
Chúng tôi nhận thấy rằng thay đổi này có thể khiến một số lỗi đáng kể trong các cơ sở mã của bạn trở nên không hợp lệ, đặc biệt nếu bạn có thói quen đặt các lệnh chặn trong mã thư viện. Để giảm bớt gánh nặng này, chúng tôi có một số đề xuất:
- Để di dời các mục chặn không hợp lệ mới của bạn đến vị trí chính của chúng, chúng tôi khuyên bạn nên kết hợp các tiện ích
add-comments
vàremove-comments
tiện ích được cung cấp trong công cụ Luồng. Việc chạy./tool remove-comments
sẽ xóa mọi nhận xét không còn chặn lỗi vì chúng không nằm trên vị trí chính và./tool add-comments
sẽ đặt các lỗi mới trên các vị trí không được giải đáp. Tập./tool
lệnh có thể được truy cập bằng cách sao chép kho lưu trữ Luồng trên GitHub. - Việc ngăn chặn không có mã lỗi sẽ tiếp tục loại bỏ bất kỳ và tất cả các lỗi trên vị trí của chúng, nhưng khi chúng tôi triển khai tính năng mã lỗi, bạn có thể thêm mã thích hợp vào cơ sở mã của mình thông qua quy trình tương tự như trên. Xóa tất cả nhận xét cũ của bạn và thêm lại chúng với
add-comments
sẽ bao gồm mã lỗi trong nhận xét mới được thêm vào.