Phân tích tĩnh

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 stringnumber 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
Mã từ
  ví dụ trước, hiển thị trong IDE kèm theo thông báo lỗi hiển thị trong
  cửa sổ bật lên.
VSCode cho biết rằng bạn đã chuyển sai nhập.

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 fibonaccinumber.

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.