Phân tích tĩnh là một loại kiểm thử cung cấp quy trình kiểm tra tự động mà không thực sự chạy mã đó hay phải viết chương trình kiểm thử tự động. Bạn đã có thể đã thấy loại hình kiểm thử này nếu bạn sử dụng IDE như VSCode – loại việc kiểm tra do TypeScript thực hiện là một loại phân tích tĩnh và có thể hiển thị dưới dạng các đường ngoằn ngoèo bên dưới lỗi hoặc cảnh báo.
ESLint
ESLint là một công cụ có thể cung cấp phản hồi về các vấn đề có thể xảy ra trong cơ sở mã. Những vấn đề này có thể thuộc loạian toàn,nhưng có lỗi hoặc hành vi không chuẩn theo cách riêng của họ. ESLint cho phép bạn áp dụng một số quy tắc được kiểm tra cơ sở mã của bạn, bao gồm nhiều mã trong phần "được đề xuất" thiết lập.
Một ví dụ điển hình về quy tắc ESLint là
no-unsafe-finally
. Điều này ngăn bạn viết các câu lệnh sửa đổi mã
luồng điều khiển bên trong khối finally
. Đây là một quy tắc rất hiệu quả vì khi làm điều này
là một cách viết JavaScript khác thường có thể khó tuân theo. Tuy nhiên,
cũng có thể phát hiện được
điều gì đó mà quy trình đánh giá mã lành mạnh.
try {
const result = await complexFetchFromNetwork();
if (!result.ok) {
throw new Error("failed to fetch");
}
} finally {
// warning - this will 'overrule' the previous exception!
return false;
}
Do đó, ESLint không thể là một giải pháp thay thế cho một quy trình đánh giá lành mạnh (và hướng dẫn xác định giao diện cơ sở mã của bạn), vì nó sẽ không hoạt động để nắm bắt mọi phương pháp tiếp cận không chính thống mà nhà phát triển có thể cố gắng giới thiệu vào cơ sở mã của bạn. Hướng dẫn về các phương pháp bằng tiếng Anh của Google có một phần ngắn nói về "cách đơn giản hoá".
ESLint cho phép bạn phá vỡ quy tắc và chú thích mã là "được phép". Ví dụ: bạn có thể cho phép logic trước đó bằng cách chú thích như sau:
finally {
// eslint-disable-next-line no-unsafe-finally
return false;
}
Nếu bạn thấy mình liên tục vi phạm quy tắc, hãy cân nhắc tắt quy tắc đó. Các các công cụ khuyến khích bạn viết mã theo một cách nhất định, nhưng nhóm của bạn có thể được sử dụng viết mã theo một cách khác và đã nhận thức được những rủi ro của việc đó phương pháp tiếp cận.
Cuối cùng, việc bật các công cụ phân tích tĩnh trên cơ sở mã lớn có thể tạo ra về tiếng ồn không hữu ích (và khối lượng công việc cần tái cấu trúc) đối với mã hoạt động bình thường tốt lắm. Vì vậy, bạn có thể dễ dàng kích hoạt sớm trong vòng đời của một dự án.
Trình bổ trợ ESLint để hỗ trợ trình duyệt
Bạn có thể thêm một trình bổ trợ vào ESLint để gắn cờ việc sử dụng các API không phổ biến được hỗ trợ hoặc không được danh sách trình duyệt mục tiêu của bạn hỗ trợ. Chiến lược phát hành đĩa đơn eslint-plugin-compat có thể cảnh báo bạn khi một API có thể không có sẵn cho người dùng của bạn, vì vậy bạn không phải liên tục theo dõi cho bản thân.
Kiểm tra kiểu để phân tích tĩnh
Khi học JavaScript, các nhà phát triển mới thường làm quen với ý tưởng đó là một ngôn ngữ được nhập yếu. Tức là bạn có thể khai báo một biến dưới dạng một loại, sau đó sử dụng cùng một vị trí cho một loại dữ liệu hoàn toàn khác. Ngôn ngữ này tương tự như Python và các ngôn ngữ tập lệnh khác, nhưng không giống như được biên dịch như C/C++ và Rust.
Dạng ngôn ngữ này có thể sẽ phù hợp để bắt đầu—và có vẻ như
tính đơn giản đã làm cho JavaScript trở nên phổ biến
nhưng đó thường là một điểm thất bại
đối với một số cơ sở mã hoặc ít nhất là một tính năng gây ra lỗi gây nhầm lẫn
xảy ra. Ví dụ: bằng cách truyền number
, trong đó string
hoặc một kiểu đối tượng
như dự kiến, giá trị được nhập không chính xác có thể truyền qua
trước khi gây ra TypeError
khó hiểu.
TypeScript
TypeScript là giải pháp chủ đạo nhất cho việc JavaScript không có khả năng nhập của bạn. Khoá học này sử dụng nó một cách rộng rãi. Mặc dù đây không phải là khoá học về TypeScript có thể là một phần quan trọng trong hộp công cụ của bạn vì nó cung cấp phân tích tĩnh.
Ví dụ nhanh: mã này dự kiến sẽ được cung cấp một lệnh gọi lại chấp nhận một
Tên string
và number
tuổi:
const callback = (name: string, age: string): void => {
console.info(name, 'is now', age, 'years old!');
};
onBirthday(callback);
Tạo lỗi sau đây khi chạy qua TypeScript, hoặc ngay cả khi di chuột trong IDE:
bad.ts:4:12 - error TS2345: Argument of type '(name: string, age: string) => void' is not assignable to parameter of type '(name: string, age: number) => void'.
Types of parameters 'age' and 'age' are incompatible.
Type 'number' is not assignable to type 'string'.
4 onBirthday(callback);
~~~~~~~~
Found 1 error in bad.ts:4
Cuối cùng, mục tiêu của việc sử dụng TypeScript là để ngăn chặn các lỗi như thế này—
độ tuổi phải là number
, chứ không phải string
—được đi vào dự án của bạn. Chiến dịch này
lỗi có thể khó phát hiện bằng các loại kiểm thử khác.
Ngoài ra, hệ thống loại có thể đưa ra phản hồi trước khi viết kiểm thử.
Việc này có thể giúp quá trình viết mã dễ dàng hơn bằng cách cung cấp cho bạn thông tin phản hồi sớm
về lỗi nhập khi bạn đang phát triển phần mềm chứ không phải khi mã
cuối cùng sẽ chạy.
Phần khó khăn nhất khi sử dụng TypeScript là thiết lập TypeScript đúng cách. Mỗi
dự án cần một tệp tsconfig.json
, mặc dù tệp này chủ yếu được tsc
sử dụng
công cụ dòng lệnh cũng được các IDE như VSCode đọc cùng với nhiều
các công cụ và công cụ xây dựng, bao gồm cả Vitest. Tệp này chứa hàng trăm
và bạn có thể tìm thấy một số tài nguyên hữu ích để thiết lập tại đây:
Mẹo TypeScript chung
Khi thiết lập và sử dụng TypeScript thông qua tệp tsconfig.json
, hãy giữ cho
những lưu ý sau:
- Đảm bảo các tệp nguồn của bạn thực sự được đưa vào và kiểm tra. Nếu một tệp "không có lỗi" một cách bí ẩn, đó có thể là do khoá đó không được kiểm tra.
- Mô tả rõ ràng các loại và giao diện bên trong tệp
.d.ts
, thay vì khi chúng được mô tả ngầm khi bạn viết hàm, có thể giúp cơ sở mã dễ kiểm thử hơn. Việc viết các nội dung mô phỏng và "giả mạo" sẽ dễ dàng hơn các phiên bản của khi các giao diện có liên quan đều rõ ràng. .
TypeScript ngầm ẩn mọi
Một trong những tuỳ chọn cấu hình mạnh mẽ và xứng đáng nhất của TypeScript là
Cờ noImplicitAny
. Tuy nhiên, khó bật nhất,
đặc biệt nếu bạn đã có một cơ sở mã lớn. (Cờ noImplicitAny
là
được bật theo mặc định nếu bạn đang ở chế độ strict
.)
Cờ này sẽ khiến hàm này trả về một lỗi:
export function fibonacci(n) {
if (n <= 1) {
return 0;
} else if (n === 2) {
return 1;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
Mặc dù với tư cách độc giả, rõ ràng n
phải là một số,
TypeScript không thể xác nhận điều này một cách tự tin. Nếu bạn đang sử dụng VSCode, hãy di chuột qua
hàm sẽ mô tả nó như sau:
function fibonacci(n: any): any
Phương thức gọi của hàm này sẽ có thể truyền qua giá trị thuộc loại any
(một loại cho phép mọi loại khác), không chỉ là number
. Bằng cách bật
noImplicitAny
, bạn có thể bảo vệ loại mã này trong quá trình phát triển,
mà không cần phải viết những bài kiểm thử logic nghiệp vụ chuyên sâu để truyền mã
các loại dữ liệu không chính xác ở những vị trí cụ thể.
Cách khắc phục đơn giản ở đây là đánh dấu cả đối số n
và kiểu dữ liệu trả về của fibonacci
là number
.
Cờ noImplicitAny
không ngăn bạn rõ ràng viết any
trong
cơ sở mã của bạn. Bạn vẫn có thể viết một hàm chấp nhận hoặc trả về
loại any
. Phương thức này chỉ đảm bảo rằng bạn cung cấp một kiểu dữ liệu cho mỗi biến.