TypeScript 5.6 beta đã được phát hành, giới thiệu một số tính năng mới mạnh mẽ nhằm phát hiện các lỗi lập trình phổ biến và hỗ trợ nâng cao cho các đối tượng lặp (iterables). Những cập nhật này không chỉ cải thiện độ an toàn của code mà còn giúp đơn giản hóa quá trình phát triển. 

Trong bài viết này, hãy cùng VietnamWorks inTECH tìm hiểu về lợi ích mà những tính năng mới này hỗ trợ cho các dự án của bạn và tiềm năng cải thiện trải nghiệm lập trình của bạn khi phiên bản đầy đủ được phát hành.

1. Các phương pháp trợ giúp Iterator: Đưa các phương pháp của Array vào Iterables

Các iterable và iterator là các thành phần cơ bản trong JavaScript, cho phép duyệt qua các tập hợp. Tuy nhiên, nhiều lập trình viên cảm thấy thiếu các phương pháp như map, filter reduce trên các iterable. TypeScript 5.6 đã giải quyết vấn đề này bằng cách mang đến các phương pháp trợ giúp cho các iterable, được lấy cảm hứng từ một đề xuất ECMAScript gần đây.

Ví dụ, bây giờ bạn có thể sử dụng trực tiếp phương pháp map trên một hàm generator:

 

function* positiveIntegers() {
    let i = 1;
    while (true) {
        yield i++;
    }
}

const evenNumbers = positiveIntegers().map(x => x * 2);

for (const value of evenNumbers.take(5)) {
    console.log(value);
}

 

Tính năng này mở rộng sang các phương thức như keys(), values()entries() trên Maps và Sets, giúp người dùng dễ dàng làm việc với các cấu trúc dữ liệu này theo phong cách lập trình hàm. Ví dụ, bạn có thể đảo ngược các key và value của một Map:

 

function invertKeysAndValues<K, V>(map: Map<K, V>): Map<V, K> {
    return new Map(
        map.entries().map(([k, v]) => [v, k])
    );
}

 

Ngoài ra, bạn có thể tạo các trình lặp tùy chỉnh bằng cách mở rộng đối tượng Iterator mới:

 

class Zeroes extends Iterator<number> {
    next() {
        return { value: 0, done: false } as const;
    }
}

const zeroes = new Zeroes();
const ones = zeroes.map(x => x + 1);

 

Bạn cũng có thể điều chỉnh bất kỳ Iterables hoặc Iterators hiện có thành kiểu mới này bằng cách Iterator.from:

Iterator.from(…).filter(someFunction);

2. Giới thiệu BuiltinIterator để tăng cường an toàn kiểu dữ liệu

Kiểu BuiltinIterator mới của TypeScript cung cấp một mô hình kiểu chính xác hơn cho các iterator nội tại của iterable. Kiểu này đảm bảo rằng các phương thức như map và take có sẵn trên các iterator được tạo ra bởi các cấu trúc JavaScript tiêu chuẩn. Dưới đây là cách bạn có thể tận dụng kiểu mới này:

 

function invertKeysAndValues<K, V>(map: Map<K, V>): Map<V, K> {
    return new Map(map.entries().map(([k, v]) => [v, k]));
}

 

Hơn nữa, việc mang đến BuiltinIteratorReturn flag --strictBuiltinIteratorReturn tăng cường an toàn kiểu dữ liệu của các iterator, giúp ngăn ngừa lỗi như truy cập các thuộc tính trên các giá trị có thể chưa được xác định.

3. Các Kiểm Tra Nullish và Truthy Không Được Phép

Bạn đã bao giờ viết một biểu thức chính quy và quên gọi .test(...) trên nó, hoặc vô tình sử dụng => thay vì >= trong một phép so sánh? Những lỗi này có thể dẫn đến các lỗi khó phát hiện nhưng bây giờ TypeScript 5.6 giúp phát hiện các lỗi này dễ dàng hơn bao giờ hết.

 

if (/0x[0-9a-f]/) {
    // Oops! This block always runs.
}

 

TypeScript 5.6 hiện xác định loại biểu thức này là luôn đúng và đánh dấu lỗi. Tương tự, nó bắt lỗi trong các biểu thức mà thứ tự ưu tiên toán tử bị hiểu sai, chẳng hạn như:

 

function isValid(value: string | number, options: any, strictness: "strict" | "loose") {
    if (strictness === "loose") {
        value = +value;
    }
    return value < options.max ?? 100; // Error: Right operand of ?? is unreachable
}

 

Những kiểm tra này đảm bảo code của bạn hoạt động đúng như mong đợi bằng cách phát hiện sớm các vấn đề trong quá trình phát triển.

4. Cho phép các định danh mô-đun tùy ý

Các mô-đun JavaScript có thể xuất các ràng buộc với tên không phải là định danh JavaScript hợp lệ. TypeScript 5.6 hỗ trợ tính năng này, cho phép các lập trình viên nhập và sử dụng các ràng buộc đó một cách liền mạch. Điều này đặc biệt hữu ích cho khả năng tương tác với các ngôn ngữ và công cụ khác tạo ra code.

5. Cải tiến trong TypeScript 5.6

5.1. Tùy chọn noUncheckedSideEffectImports

Trong JavaScript, side effect import thường được sử dụng để thực hiện các hành vi toàn cục như đăng ký biến toàn cục hoặc thêm polyfill. Tuy nhiên, TypeScript thường bỏ qua những side effect import mà nó không tìm thấy, điều này có thể khiến bạn không phát hiện các lỗi chính tả hoặc lỗi tiềm ẩn khác. 

Để khắc phục vấn đề này, TypeScript 5.6 đã thêm một tùy chọn mới là --noUncheckedSideEffectImports. Khi bật tùy chọn này, nếu TypeScript không tìm thấy file mà bạn đang cố import, nó sẽ ngay lập tức báo lỗi để bạn biết và fix. Nhờ đó, code của bạn sẽ trở nên an toàn và đáng tin cậy hơn.

import “non-existent-module”;

Đối với những trường hợp bạn cần nhập các tài liệu như file CSS, bạn có thể sử dụng một cách khai báo đặc biệt gọi là "khai báo mô-đun ambient " để tránh lỗi.

 

// ./src/globals.d.ts
declare module "*.css" {}

 

5.2. Tùy chọn noCheck

Tùy chọn --noCheck cho phép TypeScript bỏ qua việc kiểm tra kiểu cho tất cả các tệp đầu vào. Điều này đặc biệt hữu ích cho việc tách biệt tạo tệp JavaScript khỏi kiểm tra kiểu, cho phép thực hiện các tác vụ này song song.

 

tsc --noCheck
tsc --noEmit

 

Phương pháp này tăng tốc quá trình build bằng cách ưu tiên tạo ra các tệp đầu ra trước, sau đó thực hiện kiểm tra kiểu dữ liệu toàn diện.

5.3. Cho phép build với lỗi trung gian

Trong các phiên bản trước, sử dụng chế độ --build sẽ dừng quá trình build nếu gặp bất kỳ lỗi nào trong các phụ thuộc upstream. Sự cứng nhắc này thường cản trở tiến độ của các dự án downstream. TypeScript 5.6 giờ đây cho phép quá trình build tiếp tục ngay cả khi có lỗi trung gian, tạo ra các tệp đầu ra dựa trên khả năng tốt nhất.

Thay đổi này hữu ích trong các trường hợp như nâng cấp dự án, nơi các phụ thuộc có thể được nâng cấp từng bước mà không chặn toàn bộ quá trình build.

5.4. Chẩn đoán ưu tiên vùng trong editor

Việc chỉnh sửa các tệp lớn trong TypeScript đôi khi bạn có thể cảm thấy chậm chạp do cần rất nhiều thời gian để kiểm tra toàn bộ tệp. TypeScript 5.6 giới thiệu chẩn đoán ưu tiên vùng, tập trung vào vùng hiện đang hiển thị của tệp trong Editor, giúp cho việc chỉnh sửa nhanh chóng trở nên mượt mà hơn.

Trong các thử nghiệm, chẩn đoán dựa trên khu vực ban đầu mất thời gian ít hơn nhiều so với kiểm tra toàn bộ tệp, cải thiện trải nghiệm chỉnh sửa trong các tệp lớn.

5.5. Tìm kiếm tệp Ancestor Configuration để xác định quyền sở hữu dự án

Khi một tệp TypeScript được tải trong editor, editor sẽ tìm kiếm tệp tsconfig.json tương ứng. Trước đây, tìm kiếm này sẽ dừng lại ở tệp tsconfig.json đầu tiên được tìm thấy. TypeScript 5.6 tiếp tục tìm kiếm lên cây thư mục để tìm các tệp tsconfig.json phù hợp khác, cung cấp nhiều tính linh hoạt hơn trong tổ chức dự án.

5.6. Những thay đổi về hành vi đáng chú ý

  • .tsbuildinfo luôn được ghi lại: TypeScript sẽ luôn tạo ra một tệp .tsbuildinfo cho mọi dự án khi sử dụng tùy chọn --build, nhằm hỗ trợ các tính năng mới như build liên tục và --noCheck.

  • Tôn trọng phần mở rộng tệp và package.json trong node_modules: TypeScript sẽ xử lý đúng các phần mở rộng tệp và thông tin trong package.json khi tìm kiếm mô-đun, giúp ngăn ngừa các lỗi import không mong muốn.

Kết luận

Để khám phá các tính năng này bạn có thể thử nghiệm phiên bản beta hoặc nightly của TypeScript 5.6 và trải nghiệm các khả năng nâng cao của nó. Các tính năng mới không chỉ đơn giản hóa quá trình phát triển mà còn cung cấp các công cụ mạnh mẽ để ngăn chặn các lỗi lập trình phổ biến, làm cho TypeScript trở thành một công cụ mạnh mẽ hơn cho các lập trình viên.

VietnamWorks inTECH

TẠO TÀI KHOẢN MỚI: XEM FULL “1 TÁCH CODEFEE” - NHẬN SLOT TƯ VẤN CV TỪ CHUYÊN GIA - CƠ HỘI RINH VỀ VOUCHER 200K