3 điểm bởi GN⁺ 2024-07-26 | 1 bình luận | Chia sẻ qua WhatsApp
  • PR Node.js #53725 đã được hợp nhất, bổ sung hỗ trợ thử nghiệm cho việc chạy tệp TypeScript thông qua cờ --experimental-strip-types
  • Tính năng này loại bỏ cú pháp kiểu khỏi mã nguồn TypeScript để chuyển đổi thành mã nguồn JavaScript, và không thực hiện kiểm tra kiểu trong quá trình chuyển đổi
  • Bản triển khai ban đầu không chuyển đổi các tính năng riêng của TypeScript như Enum, namespaces, nên chỉ giới hạn ở những đoạn mã có thể trở thành JavaScript chỉ bằng cách loại bỏ kiểu
  • @swc/wasm-typescript được chọn để triển khai, vì sự đơn giản: không cần thêm Rust hay Go vào toolchain của Node.js
  • Trong phần thảo luận, các ràng buộc chính được đề cập gồm quy tắc phần mở rộng tệp bắt buộc của ESM, thông lệ TypeScript dùng import .js trỏ tới tệp .ts thực tế, cùng chi phí của sourcemap và vị trí trong error stack

Cách hoạt động của --experimental-strip-types

  • Khi đặt --experimental-strip-types, Node.js có thể chạy tệp TypeScript
  • Node.js transpile mã nguồn TypeScript thành mã nguồn JavaScript
  • Trong quá trình transpile, Node.js không thực hiện kiểm tra kiểu và loại bỏ thông tin kiểu
  • Ví dụ như sau
const foo: string = "foo";
const foo = "foo";

Lý do chỉ chọn loại bỏ kiểu và các giới hạn ban đầu

  • Trọng tâm của PR này là loại bỏ cú pháp kiểu trong cú pháp TypeScript
  • Các runtime khác đôi khi chuyển đổi những tính năng riêng của TypeScript không có trong JavaScript, như enum, sang JavaScript
  • Bản triển khai ban đầu của PR này không thực hiện các chuyển đổi như vậy
    • Không thể dùng Enum
    • Không thể dùng namespaces
    • Các tính năng riêng khác của TypeScript cũng không thuộc phạm vi chuyển đổi
  • PR có kèm hướng dẫn tham khảo typescript.md trong các thay đổi của PR để biết chi tiết triển khai và giới hạn

Chọn @swc/wasm-typescript làm công cụ triển khai

  • @swc/wasm-typescriptmột gói nhỏ, gồm một tệp wasm và một tệp JavaScript để binding với nó
  • Các công cụ khác có yêu cầu phải thêm Rust hoặc Go vào toolchain của Node.js
  • SWC cũng đang được Deno dùng cho cùng mục đích, và tác giả PR xem đây là một lựa chọn đã được kiểm chứng
  • Trong tương lai, tính năng này có thể được triển khai ở lớp native
  • PR này tham chiếu tới nodejs/loaders#217

Thảo luận về phân giải import và phần mở rộng

  • Import không có phần mở rộng như import foo from "./foo" không được hỗ trợ
  • Node.js ESM có quy tắc mandatory file extensions, nên việc không hỗ trợ import không có phần mở rộng được xem là hành vi có chủ đích
  • Có ý kiến cho rằng trong các codebase module TypeScript, ngay cả khi tệp thực tế là .ts, câu lệnh import vẫn thường dùng phần mở rộng .js
    • Ví dụ: import foo from './foo.js'
    • Trường hợp trong hệ thống tệp thực tế không có ./foo.js mà chỉ có ./foo.ts
  • Tác giả PR cho rằng vấn đề này có thể được xử lý trong các vòng lặp sau, và việc suy đoán phần mở rộng sẽ cần thêm kiểm tra hệ thống tệp cùng heuristic
    • Nếu không có ./foo.js thì kiểm tra ./foo.ts
    • Nếu không có ./foo.ts thì kiểm tra ./foo.js
  • Thảo luận này được theo dõi tại nodejs/loaders#208

Vị trí nguồn, sourcemap và error stack

  • Trong quá trình review, có ý kiến rằng trong ngắn hạn cần vị trí nguồn chính xác trong error stack
  • Một cách khả dĩ là không thay đổi vị trí nguồn trong quá trình loại bỏ kiểu, qua đó tránh việc tạo và ánh xạ sourcemap
  • Sourcemap có chi phí về mức sử dụng bộ nhớ và hiệu năng, đồng thời có ràng buộc là không đơn giản
  • Tác giả PR cho rằng vì SWC đã hỗ trợ sourcemap, có thể thêm một cờ để kích hoạt tính năng này
  • Cũng có thể yêu cầu SWC cung cấp tùy chọn thay thế cú pháp bị loại bỏ bằng khoảng trắng để không làm thay đổi error stack gốc

Các vấn đề thiết kế còn lại trước khi ổn định

  • Hỗ trợ TypeScript được chia thành hai trục
    • Loại bỏ cú pháp kiểu
    • Điều chỉnh quy tắc phân giải để chấp nhận tệp .ts
  • Có lo ngại rằng việc thay đổi quy tắc phân giải có thể xung đột với các loader TypeScript hiện có
  • Tác giả PR trả lời rằng PR này không override quy tắc phân giải, và cần có phần mở rộng tệp
  • Có ý kiến cho rằng có thể hỗ trợ dạng import './file.ts' thông qua allowImportingTsExtensions, và cách này cũng phù hợp với Deno
  • Nếu muốn chạy trực tiếp cùng một tệp nguồn và cũng tạo đầu ra JavaScript bằng công cụ build, trách nhiệm đổi file.ts thành file.js có thể thuộc về công cụ build

Hợp nhất và các công việc tiếp theo

  • PR được hợp nhất vào nodejs:main ngày 24/07/2024
  • Quy mô thay đổi gồm 8 commit, 89 tệp, thêm 2.190 dòng và xóa 25 dòng
  • PR được gắn các nhãn như semver-minor, experimental, module, esm, notable-change
  • Đã có thảo luận về việc có nên đề cập tính năng này trên trang hướng dẫn TypeScript của website hay không, và PR cập nhật liên quan cũng được liên kết
  • Việc đưa phiên bản TypeScript mà binary Node dùng để loại bỏ kiểu vào metadata phát hành cũng được thảo luận như một issue tiếp theo

1 bình luận

 
GN⁺ 2024-07-26
Ý kiến trên Hacker News
  • Xóa kiểu TypeScript là điều không thể nếu không có cú pháp TypeScript. Việc xóa kiểu không phải là thao tác ở mức token, và cú pháp TypeScript vẫn tiếp tục thay đổi
    Ví dụ, foo < bar & baz > ( x ) trong TypeScript 1.5 được phân tích như (foo (x))bar&baz không phải là biểu thức kiểu hợp lệ, nhưng sau khi toán tử kiểu giao nhau được thêm vào thì nó được phân tích thành foo<(bar & baz)>(x) và bị khử kiểu thành foo(x)
    Nếu muốn tiếp tục dùng các tính năng TypeScript mới nhất thì phải biên dịch sang JS hoặc liên tục cập nhật phiên bản Node, và với các nhóm thích ở lại Node LTS thì đây có thể là một sự đánh đổi khó chấp nhận

    • Có vẻ như đội ngũ Node đã cân nhắc vấn đề này rồi. Vì Node bundle npm nhưng vẫn có tiền lệ cho phép nâng cấp riêng, nên cũng có thảo luận rằng bộ chuyển đổi TypeScript có thể làm tương tự
      Cách này là giữ một phiên bản ổn định trong core, còn nếu TypeScript phát hành tính năng mới, thay đổi phá vỡ tương thích, hoặc người dùng muốn dùng tính năng thử nghiệm mới thì sẽ nâng cấp riêng qua NPM
      Làm vậy sẽ tránh việc người dùng bị khóa cứng, đồng thời vẫn có thể hỗ trợ một phiên bản TypeScript cụ thể trong vòng đời 3 năm của bản phát hành Node.js: https://github.com/nodejs/loaders/issues/217
    • Xét từ góc độ xóa kiểu, số phiên bản TypeScript có cú pháp ổn định nhiều hơn rất nhiều so với giai đoạn cú pháp còn bất ổn. Việc lùi về tận 1.5 cũng là vì từ 2.x trở đi nó đã khá ổn định rồi
      Thay đổi cú pháp lớn cuối cùng có lẽ là conditional types trong 2.8, khi một cú pháp giống toán tử tam phân if được đưa vào vị trí kiểu. Nếu muốn kiểm tra kiểu đầy đủ thì mô hình kiểu đã thay đổi rất nhiều từ sau 2.x, nhưng cú pháp nhìn chung vẫn ổn định, và phần lớn đổi mới của TypeScript cũng nằm ở mô hình kiểu và suy luận kiểu
      Dù vẫn đang ở giai đoạn đầu là Stage 1, hiện cũng có nỗ lực chuẩn hóa một phần đáng kể cú pháp kiểu TypeScript cho mục đích xóa kiểu chứ không phải kiểm tra kiểu: https://github.com/tc39/proposal-type-annotations
    • Trình biên dịch cũng sẽ phải được cập nhật cùng lúc. Rốt cuộc có thể diễn đạt là “không thể nâng phiên bản TypeScript độc lập với phiên bản Node.js”, nhưng có lẽ đây không phải vấn đề quá lớn
    • Có vẻ việc dùng dấu nhỏ hơn/lớn hơn như ngoặc nhọn góc thực sự là một sai lầm
    • Những nhóm luôn bám theo TypeScript mới nhất và dùng tính năng ngôn ngữ mới có lẽ cũng sẽ bám theo cả phiên bản Node mới nhất. Theo kinh nghiệm, việc nâng cấp TypeScript thường đòi hỏi migrate hoặc sửa lỗi do lỗi mới xuất hiện nhiều hơn so với nâng cấp Node
      Các nhóm không mấy quan tâm đến tính năng mới của V8 hay Node và thích ở lại LTS cũng có khả năng ít quan tâm đến các tính năng TypeScript mới nhất hơn
  • Nếu Node.js có thể chạy trực tiếp file TypeScript thì trình biên dịch TypeScript có thể chỉ còn được dùng như trình kiểm tra kiểu, thay vì để xóa kiểu và chuyển đổi sang JavaScript. Cách này khá giống Python, nơi trình kiểm tra kiểu kiểm tra type rồi để nguyên, còn trình thông dịch thì bỏ qua type hint
    Điều thú vị là trong Python đã xuất hiện nhiều trình kiểm tra kiểu phổ biến dùng cùng một cú pháp type hint nhưng có ngữ nghĩa khác nhau. Trong khi đó ở JavaScript thì có vẻ TypeScript gần như đã trở thành trình kiểm tra kiểu phổ biến duy nhất
    Tôi cũng từng nghe rằng trong Python có trường hợp người ta không thực sự kiểm tra kiểu mà chỉ viết kiểu vào mã nguồn như một dạng cú pháp chú thích thuận tiện hơn. Nếu Node.js hỗ trợ bỏ qua kiểu thì JavaScript cũng có thể làm theo cách đó

    • Flow của Facebook vài năm trước còn khá quan trọng trong thế giới JavaScript, nhưng bây giờ có vẻ TypeScript đã thắng khá rõ ràng
    • Ngay cả khi không kiểm tra kiểu, IDE vẫn có thể dùng type hint để cải thiện tự động hoàn thành và các tính năng tương tự, nên việc thêm kiểu ở một số vị trí vẫn có ý nghĩa
    • Ngay cả bây giờ cũng có thể gắn kiểu bằng JSDoc rồi để TypeScript kiểm tra, nên không cần biên dịch. Build sẽ nhanh hơn, và bạn sẽ có mã chạy được ở mọi nơi mà không cần xử lý ma thuật hay bước loại bỏ gì ngoài chú thích
      Cá nhân tôi thấy bất tiện lớn nhất của JSDoc là cú pháp import, nhưng từ TypeScript 5.5 trở đi điều đó đã thay đổi nên không còn là vấn đề nữa
    • Node.js không phải là runtime JavaScript duy nhất. Chừng nào mọi trình duyệt còn chưa thể chạy trực tiếp TypeScript thì với trình duyệt vẫn phải biên dịch TS sang JS
      Tuy vậy, một số bundler đã làm việc này bằng các trình biên dịch không chính thức như SWC, và Node cũng đang thử nghiệm SWC cho tính năng này
      Type hint không chỉ là chú thích đơn thuần mà còn là tín hiệu để IDE đưa ra khả năng tự động hoàn thành tốt hơn, gần giống như tên gọi
    • Có một đề xuất EcmaScript theo hướng này: https://github.com/tc39/proposal-type-annotations
      Tôi cho rằng nó nên trở thành một phần của đặc tả ngôn ngữ
  • Mình tò mò hệ sinh thái NPM sẽ phản ứng thế nào nếu tính năng này trở thành mặc định thay vì nằm sau một cờ. Không rõ khi các contributor phát hành module NPM thì họ vẫn sẽ build cả phiên bản CJS và ESM, hay chỉ cần thêm engine: nodejs >= 25 vào package.json rồi bỏ qua bước build
    Cá nhân mình sẽ thích hơn nếu các module NPM có mã nguồn TS ngừng phát hành dist/.cjs, vì như vậy sẽ rõ ràng hơn là nên đặt debugger và console.log ở đâu. Với phía contributor NPM thì sức hút của việc bỏ hẳn bước build cũng sẽ rất lớn
    Nhưng chỉ cần một dependency phát hành file TS thì giả định rằng “mọi người đều nhận file TS” có thể lan rất nhanh. Ngay khi Node.js đưa chuyện này ra khỏi cờ thử nghiệm dạng opt-in, có lẽ toàn bộ cộng đồng sẽ ngầm kỳ vọng người dùng chấp nhận file TS
    Nếu vậy thì chỉ trong vài tháng, Firefox và Safari cũng sẽ bị gây áp lực phải chấp nhận, và mọi compiler JS sẽ buộc phải loại bỏ chú thích kiểu TS
    Cá nhân mình cũng thấy điều đó ổn. Bên dùng TS hiện cũng đang phải đưa vào module NPM một bước chuyển đổi để biến mã TS thành JS và .d.ts, chỉ để hỗ trợ một nhóm người dùng JS mang tính giả định nào đó. Nhưng nếu Node chấp nhận file .ts, mình thắc mắc sẽ có cơ chế nào để ngăn việc nhà phát hành NPM vô tình bỏ bước chuyển đổi đó mà không nhận ra là mọi thứ đã hỏng, rồi dừng phát hành file js/d.ts

    • Ryan Dahl đang tạo một package registry mới tên là JSR để giải quyết vấn đề này
      Cách làm là có thể đưa mã TypeScript lên mà không cần bước build, và khi lập trình viên khác cài vào thì họ sẽ thấy mã nguồn TypeScript gốc thay vì JavaScript đã được chuyển đổi
    • Không hỗ trợ chạy file .ts bên trong node_modules. Đây là một trong những ràng buộc chính để tránh phá vỡ hệ sinh thái
    • Các thư viện TypeScript cũ đang được duy trì hiện vẫn chuyển đổi sang .cjs.mjs cho npm, nên có lẽ họ sẽ phát hành cả ba phiên bản
      Còn nếu là dự án mới viết từ đầu thì có thể chỉ phát hành TypeScript và không chuyển đổi
      Sửa: theo bình luận anh em của satanacchio, người có vẻ là tác giả PR và là thành viên ủy ban chỉ đạo kỹ thuật của Node.js, hỗ trợ TS chỉ áp dụng cho mục cấp cao nhất chứ không áp dụng cho thư viện bên trong node_modules
    • Mình muốn phát hành chính mã nguồn .ts của mình lên npm, nhưng nhóm TypeScript trước giờ phản đối rất mạnh vì các vấn đề tsconfig và hiệu năng. Dù vậy mình vẫn hy vọng
  • Biết đâu một ngày nào đó Node có thể phản chiếu lúc runtime các kiểu này ngay trong JS
    Nếu làm được thì lợi ích sẽ rất lớn. Trong Python có thể phản chiếu kiểu, nên những công cụ tuyệt vời như pydantic có thể sinh ra phần kiểm tra từ chính kiểu dữ liệu
    Chỉ với một chuẩn ký pháp duy nhất, bạn có thể có kiểm tra kiểu, kiểm tra dữ liệu lúc runtime, tạo API và tạo tài liệu API
    Còn trong JS hiện nay, các công cụ như Zod về cơ bản phải phát minh lại những gì TypeScript đã làm, kiểu như const mySchema = z.string();

    • z.string() của Zod không chỉ cung cấp an toàn kiểu như TypeScript. TypeScript cung cấp kiểm tra kiểu tại thời điểm biên dịch, còn Zod bổ sung xác thực và phân tích lúc runtime
      z.string() biến mySchema thành một schema dạng hàm có thể parse và validate. mySchema.parse("some data") sẽ thành công, còn mySchema.parse(321) sẽ ném ra ngoại lệ
      Mình đã dùng nó ở những chỗ cần xác thực lúc runtime và kiểm tra trong tiến trình, thấy hoạt động khá tốt, đồng thời cũng có thể rút ra kiểu như const A = z.string(); type A = z.infer; // string
      Tức là nếu định nghĩa kiểu trước trong Zod rồi suy luận kiểu từ đó, bạn sẽ có cả kiểm tra kiểu lúc biên dịch lẫn kiểm tra kiểu lúc runtime. Dù vậy, với codebase nhỏ phát triển nhanh thì có thể là hơi quá tay, nhưng trong các tình huống cần xác thực trong tiến trình thì nó khá hữu ích và khối lượng công việc cũng không lớn
    • Gần đây trọng tâm của nhóm TypeScript nghiêng khá nhiều về việc đồng bộ với ngôn ngữ JavaScript, và các tính năng mới như kiểu runtime gần như đã bị loại khỏi ưu tiên, hoặc ít nhất bị đẩy xuống sau đề xuất kiểu dữ liệu của JavaScript trong TC39. Vấn đề dùng decorator cho biến ngoài cấu trúc class trước đây cũng tương tự
      Tuy vậy, TypeScript có cho phép plugin. Dù không được dùng nhiều, chúng có thể thêm vào ngôn ngữ các tính năng khác được chuyển đổi sang JavaScript đầu ra
      Có một plugin liên quan đến kiểu runtime là Typia, cho phép dùng chữ ký kiểu TypeScript ở runtime trong các guard như assert(myValue). Nó chặn lời gọi hàm này và sinh ra các câu lệnh if exhaustive trong JavaScript đã chuyển đổi để kiểm tra tính chất của biến được truyền vào
      Có lẽ trong 4~6 năm tới chuyện này chưa trở thành một phần của ngôn ngữ, nhưng ngay hôm nay đã có các thư viện cho phép làm việc như vậy
    • Nếu JS một ngày nào đó thêm kiểm tra kiểu thì mình hy vọng họ sẽ không chọn TypeScript
      Thứ thực sự cần là một hệ thống kiểu sound, nhưng TS thì cố ý không sound. Cần một hệ thống kiểu không cho phép những thói quen lập trình tệ như TS, và buộc dùng các thiết kế giúp chương trình chạy nhanh hơn. Cần một hệ thống kiểu Hindley-Milner
      Nếu muốn biến module thành mã có kiểu, chỉ cần thêm "use type" là được. Chế độ này nên cấm những phần xấu như ép kiểu, đồng thời ngăn các yếu tố làm giảm hiệu năng như đổi hình dạng đối tượng, đổi kiểu giá trị, hoặc tạo mảng trộn lẫn đủ loại giá trị
      Dữ liệu đi vào từ module không có kiểu thì phải được chuyển đổi, hoặc nếu không thể chuyển đổi thì ném lỗi; khi đó compiler có thể tối ưu sâu mã có kiểu với bảo đảm kiểu mạnh hơn và không có rủi ro phải bỏ dở giữa chừng
    • Không rõ điều này có nghĩa là Node có thể biết một ngoại lệ có phải là lớp con của ValueError hay không, hoặc một đối tượng có phải là instance của SomeClass hay không. Mình mới học TS nên vẫn nghĩ ngoài mảng, đối tượng, số và chuỗi thì JS không có các kiểu khác, còn Zod hay các hàm type guard thì chỉ trả về các đối tượng thường theo kiểu “cứ tin tôi đi”
  • Trải nghiệm lập trình viên của Bun ở mảng này đạt đến mức khá chưa từng có, và giờ hầu hết các trường hợp sử dụng đã được bao phủ, hoặc ít nhất Bun không còn bị crash khi viết script chạy bằng bun run
    Trong khi đó Node thậm chí không thể cấu hình để không bắt buộc phần mở rộng trong import, và cũng không thể để tsc tự động gắn phần mở rộng .js vào kết quả biên dịch, nên phải thêm bundler
    Hỗ trợ TypeScript native có lẽ sẽ giải quyết khá nhiều bất tiện nhỏ này, nhưng ngay cả khi được ổn định hóa thì cũng khó tưởng tượng trải nghiệm người dùng hay hiệu năng của nó có thể ngang Bun

    • Phần mở rộng nên là bắt buộc. Không thể dò đường dẫn trên mạng như với đĩa cục bộ, và runtime kết nối mạng như trình duyệt là rất quan trọng với JavaScript
    • Tôi rất thích Bun, nhưng Deno vẫn trưởng thành hơn, ổn định hơn và có nhiều tính năng hơn. Nó có worker ổn định, HTTP/2, và tùy trường hợp sử dụng thì V8 có thể nhanh hơn JSC
      Trải nghiệm lập trình viên và công cụ cũng thuộc hàng tốt nhất. Deno còn có thể kiểm tra kiểu, và nếu nhớ không nhầm thì có tích hợp TSC
      Bun rất nổi, nhưng với công việc nghiêm túc thì hiện tại Deno rõ ràng là lựa chọn tốt hơn. Dù vậy, tầm nhìn và tốc độ thực thi của Bun vẫn rất ấn tượng và là điều tốt cho lập trình viên
    • Tôi đã thử Bun hai lần, cách nhau vài tháng, nhưng trên Windows thì chạy bun install đều thất bại nên chưa lần nào hoạt động tử tế cả: https://github.com/search?q=repo%3Aoven-sh%2Fbun+bun+install...
    • “Chưa từng có tiền lệ” thì chắc là nếu bỏ Deno ra thôi
    • Có cảm giác Bun vẫn còn quá thô. Nó được viết bằng Zig mà còn chưa ra 1.0
  • Tôi đã mong có TypeScript runtime từ lâu và cũng thật sự rất thích TypeScript, nhưng buồn cười là đã rời bỏ Java từ lâu rồi cuối cùng lại đi tìm một thứ gần với Java hơn rất nhiều
    Có vẻ rốt cuộc thứ chúng ta muốn là Java có JIT, hệ thống kiểu phong phú hơn, và kiểu hóa dần dần. Hệ sinh thái npm cũng có nhiều điểm tệ, nhưng dùng thư viện trong hệ này ít áp lực hơn nhiều và cũng vui hơn
    Thật ngạc nhiên là Rust ở đầu kia của phổ ngôn ngữ nhưng đôi khi cũng cho cảm giác tương tự
    Sửa lại: dùng từ JIT là không phù hợp. Tôi viết JIT một cách lười biếng, nhưng điều tôi muốn nói là khác biệt về thời gian khởi động và lúc chạy khi thực thi thứ gì đó trên JVM và V8. Java cho cảm giác nặng nề, còn hệ sinh thái JavaScript thì linh hoạt hơn nhiều

    • Java chính là thứ đã làm thuật ngữ JIT trở nên phổ biến theo đúng nghĩa đen, nên tôi không hiểu “Java có JIT” nghĩa là gì
      Tôi cũng hoàn toàn không thấy TypeScript gần Java hơn ở điểm nào. Thứ hai bên cùng chia sẻ chỉ là cái tên sai lệch “Javascript” và việc hỗ trợ lập trình mệnh lệnh, còn lại thì tôi thấy rất khác nhau
    • Theo trải nghiệm của tôi thì TypeScript tốt hơn Java rất nhiều. Ít dài dòng hơn hẳn và linh hoạt hơn
    • Cá nhân tôi thấy dùng TypeScript dễ chịu hơn Java rất nhiều. Đặc biệt nếu tránh các phần hơi khiếm khuyết của class và tập trung vào interface với function thì tính tiện dụng tốt hơn hẳn
      Tuy nhiên, thứ có trong Java mà tôi nhớ ở TypeScript là phản chiếu kiểu lúc runtime. Hệ sinh thái TypeScript có vô số cách lách để làm điều này, nhưng tôi thấy tất cả đều hơi xấu xí
    • Java có JIT. Và tôi tò mò không biết hệ thống kiểu của TypeScript phong phú hơn Java ở điểm nào
    • Tôi cũng ở vị trí tương tự. Cá nhân tôi muốn thư viện chuẩn và hệ sinh thái của C# nhưng bỏ đi những phần legacy hiện tại hoặc đã gần như bị loại bỏ, rồi bổ sung thêm sự đơn giản và sức mạnh của kiểu đại số có cấu trúc
      AoT cũng ổn, và sẽ tốt nếu có tùy chọn một file nhị phân duy nhất. Lý tưởng nhất là không có runtime, có thể loại bỏ thông minh, và càng tốt hơn nếu vẫn chạy JIT được trên trình duyệt
      Tôi cũng muốn các tiện ích của compiler và trình kiểm tra kiểu như exhaustive pattern matching
  • Tính năng Deno mà tôi thích đang đi thẳng vào Node. Rất tuyệt
    Có khi giờ tôi sẽ không còn phải luôn cài esbuild chỉ để loại bỏ kiểu nữa. Tôi rất mong việc viết rồi dùng script bằng TypeScript sẽ dễ hơn nhiều
    Gần đây tôi vẫn thích Python hơn cho các script dùng một lần, nhưng về mặt kiểu thì cá nhân tôi thấy TypeScript tốt hơn Python. Đặc biệt với các script lớn mà vài tháng sau phải xem lại thì lợi ích của kiểu rất rõ

  • Đây đúng là một tháng đầy biến động với Node. Đầu tiên là node:sqlite được thêm trong v22.5.0, giờ lại sắp có cả hỗ trợ TypeScript. Tôi thích hướng đi hiện tại của Node

    • Có lẽ là do ảnh hưởng hoặc cạnh tranh từ Bun. Dù sao đây cũng là điều tốt cho tất cả mọi người
    • Test runner được thêm gần đây cũng rất hay
  • Tôi là người viết PR. Cứ hỏi gì cũng được

    • Tôi tò mò bước tiếp theo sẽ là gì, và bạn nhìn thấy TypeScript có tương lai ra sao trong Node cũng như toàn bộ hệ sinh thái JS
  • Tôi bắt đầu dùng Node.js cho công việc backend từ lâu, và thấy nó có nhiều ưu điểm hơn so với viết code bằng PHP, đồng thời dường như không mang theo quá nhiều vấn đề của Java
    Tuy nhiên, Node hơi thô ráp, và tạo cảm giác như một ngôn ngữ mà muốn đúng ý thì phải gắn thêm đủ thứ. Cuối cùng tôi chuyển sang dùng Go, thấy dễ dùng hơn nhiều, và dù đôi khi dài dòng hơn đáng kể, tính an toàn kiểu lại giúp việc lập trình trở nên đơn giản hơn
    TypeScript có vẻ là một lựa chọn tốt, nhưng rốt cuộc nó vẫn là một lớp chắp vá nữa. Tôi không rõ sẽ nhận được giá trị gì khi dùng TypeScript thay vì Go. Có kiểu dữ liệu rõ ràng thì tốt, nhưng nó không giải quyết những vấn đề khác của ngôn ngữ mà Go đã xử lý. Deno cũng giải quyết được một phần
    Ưu điểm lớn của Node so với Go là có thể tạo prototype rất nhanh, nhưng khi dùng TypeScript thì lợi thế đó dường như giảm đi khá nhiều. Vì vậy khó mà nói đây là một bước tiến tốt, hay là đang làm mất đi những đặc tính từng khiến Node trở thành một lựa chọn tốt

    • TypeScript là JavaScript an toàn hơn. Dùng TS thì bạn vẫn đang dùng JS
      Nhìn vào cách gọi là “lớp chắp vá”, có lẽ vấn đề không nằm ở bản thân ngôn ngữ mà là sự thiếu vắng một framework định hướng mạnh kiểu như Django, thứ quản lý mọi thứ theo mặc định. Tôi thích dùng Django, nhưng cũng khó rời khỏi con đường đã được định sẵn hơn một chút
    • Câu trả lời rõ ràng là mức độ quen thuộc với ngôn ngữ. Nếu mã frontend của dự án là JavaScript hoặc TypeScript, thì chọn Node là một quyết định dễ dàng. Có thể dùng thư viện dùng chung, kiểu dữ liệu dùng chung, v.v.
    • Có thể là vì nếu đã biết JavaScript hoặc đã có kinh nghiệm nội bộ trong công ty, thì như vậy vẫn tốt hơn là học Go. Bên tôi cũng dùng nó cùng với cdktf nhờ kinh nghiệm frontend trước đó, và nó có vẻ là lựa chọn hợp lý hơn Go