Phát hành Zod 4
(zod.dev)- Zod 4 được phát hành ở phiên bản ổn định sau 1 năm phát triển, khắc phục các giới hạn thiết kế của Zod 3 và cải thiện mạnh hiệu năng, kích thước bundle và hiệu quả biên dịch TypeScript
- Zod 3 ra mắt vào tháng 5/2021 với 2.700 GitHub stars và 600.000 lượt tải mỗi tuần, nay đã tăng lên 37.8k stars và 31 triệu lượt tải/tuần
- Trong benchmark, phân tích chuỗi nhanh hơn 14 lần, phân tích mảng nhanh hơn 7 lần, phân tích object nhanh hơn 6.5 lần; số lần khởi tạo kiểu của
tsctrong ví dụ đơn giản cũng giảm từ hơn 25.000 xuống khoảng 175 - Kích thước bundle lõi theo gzip giảm từ
12.47kbcủa Zod 3 xuống5.36kbở bản thường của Zod 4, còn Zod Mini với API hàm có thể tree-shaking chỉ còn1.88kb - Các tính năng mới gồm chuyển đổi JSON Schema, metadata registry, suy luận kiểu object đệ quy, quốc tế hóa, pretty-print lỗi, kiểu template literal,
z.stringbool(), tham sốerrorhợp nhất, vàz.discriminatedUnion()được cải thiện
Vì sao Zod 4 trở thành major version mới
- Zod 4 đã trở thành bản ổn định sau 1 năm phát triển tích cực, mang đến nền tảng nhanh hơn, nhỏ hơn và hiệu quả hơn với
tsc, đồng thời hiện thực hóa các tính năng được yêu cầu từ lâu - Zod v3.0 phát hành vào tháng 5/2021, khi đó có 2.700 GitHub stars và 600.000 lượt tải mỗi tuần
- Hiện tại Zod ghi nhận 37.8k GitHub stars và 31 triệu lượt tải mỗi tuần
- 6 tuần trước khi bản beta ra mắt, số lượt tải mỗi tuần là 23 triệu
- Sau 24 phiên bản minor, codebase của Zod 3 đã chạm tới giới hạn, và các tính năng/cải tiến được yêu cầu nhiều nhất đều cần thay đổi phá vỡ tương thích
- Zod 4 đã đóng 9 trong 10 issue công khai được upvote nhiều nhất
Hiệu năng parsing và hiệu quả biên dịch TypeScript
- Zod 4 cung cấp các benchmark có thể chạy trực tiếp từ repository
- Cải thiện hiệu năng parsing:
- Parsing chuỗi: nhanh hơn 14 lần
- Parsing mảng: nhanh hơn 7 lần
- Parsing object: nhanh hơn 6.5 lần
- Benchmark parsing object chạy Moltar validation library benchmark
- Theo
tsc --extendedDiagnostics, số lần khởi tạo kiểu giảm mạnh khi biên dịch một file đơn giản- Dùng
"zod/v3": hơn 25.000 lần - Dùng
"zod/v4": khoảng 175 lần
- Dùng
- Zod 4 thiết kế lại và đơn giản hóa generic của
ZodObjectcùng các lớp schema khác để tránh bùng nổ số lần khởi tạo - Mẫu lặp nối
.extend()và.omit()trong Zod 3 mất4000msđể biên dịch, và thêm các lệnh gọi.extend()có thể gây lỗi"Possibly infinite" - Cùng mẫu đó trong Zod 4 biên dịch trong
400ms, nhanh hơn 10 lần - Trong tương lai, khi dùng cùng compiler
tsgo, hiệu năng editor của Zod 4 có thể mở rộng tốt hơn tới các schema và codebase lớn hơn
Kích thước bundle và Zod Mini
- Kích thước bundle lõi được so sánh bằng cách bundle một script xác thực
z.boolean()đơn giản bằngrollup - Kích thước bundle lõi theo gzip:
- Zod 3:
12.47kb - Zod 4 bản thường:
5.36kb
- Zod 3:
- Bundle lõi của Zod 4 bản thường nhỏ hơn khoảng 57% so với Zod 3, tức giảm 2.3 lần
- API thiên về method của Zod vốn khó tree-shaking từ gốc, nên ngay cả script
z.boolean()đơn giản cũng kéo theo cả phần cài đặt của các method không dùng như.optional()và.array() - Zod Mini cung cấp API hàm có thể tree-shaking, tương ứng 1:1 với
zod- Khi Zod dùng method, Zod Mini thường dùng các wrapper function
- Các method parsing giống nhau giữa Zod và Zod Mini
- Dùng method
.check()tổng quát để thêm refinement
- Bản Zod thường vẫn tiếp tục được khuyến nghị cho hầu hết trường hợp sử dụng; các dự án có ràng buộc kích thước bundle cực kỳ nghiêm ngặt có thể cân nhắc Zod Mini
- Khi dùng
zod/mini, kích thước bundle gzip là1.88kb- Giảm 85% so với Zod 3, tức nhỏ hơn 6.6 lần
- Bảng so sánh: Zod 3
12.47kb, Zod 4 thường5.36kb, Zod 4 Mini1.88kb
- Xem thêm trong tài liệu
zod/mini
Metadata và JSON Schema
- Zod 4 giới thiệu một hệ thống mới để thêm metadata strongly-typed vào schema
- Metadata không được lưu trong chính schema, mà được lưu trong schema registry liên kết schema với typed metadata
- Có thể tạo registry bằng
z.registry(), và cũng có thể đăng ký tiện lợi qua method.register()của schema - Zod export
z.globalRegistry, một global registry nhận metadata tương thích JSON Schema phổ biến - Method
.meta()giúp thêm schema vàoz.globalRegistrymột cách thuận tiện - Để tương thích với Zod 3,
.describe()vẫn được giữ lại, nhưng trong Zod 4,.meta()được khuyến nghị hơn - Zod 4 cung cấp chuyển đổi JSON Schema first-party thông qua
z.toJSONSchema() - Metadata trong
z.globalRegistryđược tự động đưa vào đầu ra JSON Schema - Thông tin tùy biến cho JSON Schema được tạo ra có trong JSON Schema docs
Biểu diễn schema và tính năng kiểu mới
- Zod 4 có thể suy luận đúng kiểu object đệ quy
- Có thể biểu diễn kiểu đệ quy và kiểu đệ quy lẫn nhau
- Khác với mẫu kiểu đệ quy ở Zod 3, không cần ép kiểu
- Schema kết quả là một instance
ZodObjectthông thường và có thể dùng đầy đủ method
- Đã thêm File schema để xác thực instance
File z.templateLiteral()biểu diễn kiểu template literal của TypeScript- Các kiểu schema Zod có thể chuyển thành chuỗi sẽ lưu regex nội bộ
- Đối tượng hỗ trợ gồm chuỗi, định dạng chuỗi như
z.email(), số, boolean, bigint, enum, literal, undefined/optional, null/nullable, và template literal khác - Constructor
z.templateLiteralnối chúng lại thành một super-regex duy nhất - Các định dạng chuỗi như
z.email()được cưỡng chế đúng, nhưng custom refinement thì không - Chi tiết xem tại template literal docs
- Đã thêm các định dạng số mới để biểu diễn integer độ rộng cố định và kiểu số dấu phẩy động
- Trả về instance
ZodNumberđã được gắn sẵn các ràng buộc inclusive minimum/maximum phù hợp
- Trả về instance
- Cũng thêm các định dạng số bigint vượt ngoài phạm vi có thể biểu diễn an toàn bằng
numbercủa JavaScript- Trả về instance
ZodBigIntđã được gắn sẵn các ràng buộc inclusive minimum/maximum phù hợp
- Trả về instance
z.literal()nay có thể nhận tùy chọn nhiều giá trị
Lỗi, quốc tế hóa và định dạng chuỗi
- Zod 4 giới thiệu API
localesmới để dịch toàn cục thông báo lỗi sang nhiều ngôn ngữ - Danh sách đầy đủ các locale được hỗ trợ có tại Customizing errors và sẽ được cập nhật khi có thêm ngôn ngữ
- Zod triển khai hàm cấp cao
z.prettifyErrorđể chuyểnZodErrorthành chuỗi ở định dạng thân thiện với người dùng- Định dạng hiện chưa thể cấu hình
- Có thể sẽ thay đổi trong tương lai
- Nếu đang dùng
zod-validation-error, bạn vẫn có thể tiếp tục dùng
- Mọi định dạng chuỗi như email đều được nâng lên thành các hàm cấp cao trong module
z- Ngắn gọn hơn và thuận lợi hơn cho tree-shaking
- API method tương ứng như
z.string().email()vẫn dùng được nhưng đã ở trạng thái deprecated - Dự kiến sẽ bị loại bỏ ở major version tiếp theo
- API
z.email()hỗ trợ custom regular expression- Không có một canonical email regex duy nhất; mỗi ứng dụng có thể chọn tiêu chuẩn chặt hơn hoặc lỏng hơn
- Zod export sẵn một vài regex phổ biến để tiện sử dụng
Chuyển đổi boolean và đơn giản hóa tùy biến lỗi
z.coerce.boolean()trước đây là API đơn giản chuyển các giá trị falsy thànhfalse, truthy thànhtruefalse,undefined,null,0,"",NaN... sẽ thànhfalse- Hành vi này nhất quán với các API
z.coercekhác
- Zod 4 giới thiệu
z.stringbool()để coercion boolean tinh vi hơn theo kiểu env- Có thể tùy biến các giá trị truthy và falsy
- Xem chi tiết tại tài liệu
z.stringbool()docs
- Phần lớn thay đổi phá vỡ tương thích trong Zod 4 liên quan tới API tùy biến lỗi
- Việc tùy biến lỗi được hợp nhất vào một tham số
errorduy nhấtmessageđược thay bằngerror- Tham số
messagevẫn được hỗ trợ nhưng đã deprecated invalid_type_errorvàrequired_errorđược thay bằngerrortheo cú pháp hàmerrorMapcũng được thay bằngerrortheo cú pháp hàm
Tính kết hợp, refinement và transform
z.discriminatedUnion()nay hỗ trợ nhiều kiểu schema trước đây chưa được hỗ trợ- Bao gồm union và pipe
- Có thể dùng một discriminated union làm member của discriminated union khác, giúp có thể kết hợp
- Trong Zod 3, refinement được lưu trong lớp
ZodEffectsbao quanh schema gốc- Cấu trúc này khiến việc trộn
.refine()với các method schema khác như.min()trở nên bất tiện
- Cấu trúc này khiến việc trộn
- Trong Zod 4, refinement được lưu bên trong schema, cho phép dùng
.refine()cùng các method schema khác một cách tự nhiên - Method
.overwrite()mới biểu diễn các transform không làm thay đổi inferred type.transform()có kiểu đầu ra không thể introspect ở runtime, và hàm transform có thể trả về bất cứ thứ gì như một black box- Vì vậy không có cách an toàn để chuyển đổi sang JSON Schema
.overwrite()trả về instance của lớp gốc- Hàm overwrite được lưu như refinement và không sửa inferred type
- Các method
.trim(),.toLowerCase(),.toUpperCase()hiện được triển khai lại bằng.overwrite()
Nền tảng cho tác giả thư viện
- Việc bổ sung Zod Mini dẫn tới sự ra đời của subpackage
zod/v4/core, chứa các chức năng lõi dùng chung giữa Zod và Zod Mini zod/v4/coremở rộng Zod từ một thư viện đơn lẻ thành nền tảng xác thực nhanh có thể nhúng vào thư viện khác- Nếu đang xây dựng thư viện schema, có thể tham khảo cách triển khai của Zod và Zod Mini để xây trên
zod/v4/core - Zod cung cấp hướng dẫn For library authors
- Trình bày best practice khi xây dựng trên Zod
- Trả lời các câu hỏi phổ biến về cách hỗ trợ đồng thời Zod 3, Zod 4 và Mini
1 bình luận
Các ý kiến trên Hacker News
Tôi là tác giả, cứ hỏi tôi bất cứ điều gì. Về chính sách phiên bản, tôi đã ghi lại khá chi tiết lý do của cách tiếp cận này tại đây: https://github.com/colinhacks/zod/issues/4371
Rốt cuộc npm không được thiết kế để xử lý tốt tình huống mà Zod đang gặp phải. Hàng chục đến hàng trăm thư viện import trực tiếp interface/class của Zod rồi dùng chúng trong API công khai của chính họ, nên mỗi lần Zod tăng phiên bản major thì các thư viện đó cũng phải phát hành phiên bản major mới
Xét riêng lẻ thì điều này hợp lý, nhưng với Zod nó có thể tạo ra một trận lở tuyết phiên bản gây đau khổ cho tất cả mọi người, và có vẻ như phần lớn hệ sinh thái sẽ bị ghim mãi ở v3
Vì vậy chúng tôi chọn cách tương tự Go: thay vì package phát hành một phiên bản mới phá vỡ tương thích, nó thêm một subpath mới. Trong hệ sinh thái TypeScript, thư viện có thể chỉ đặt một peer dependency là
zod@^3.25.0, rồi import những thứ cần thiết từ"zod/v3"và"zod/v4"để hỗ trợ đồng thời cả hai phiên bảnTuy hiểu lý do phải chọn một chính sách phiên bản hơi lạ vì hoàn cảnh đặc thù, nhưng từ góc nhìn của một đội không cần lo xung đột phiên bản Zod trong dependency bắc cầu, tôi vẫn muốn có cả package
4.0.0Nếu tôi hiểu đúng thì phải đổi import sang
"zod/v4", đây là một thay đổi rất ồn ào, và có thể khá phiền vì phải dùng rule lint để bắt vấn đề IDE tự động import từ'zod'.optional()trong TypeScript có nằm trong nhóm 9–10 issue hàng đầu được giải quyết không: https://github.com/colinhacks/zod/issues/635Đây là nỗi đau lớn nhất của tôi với Zod, nhưng Zod vẫn quá tốt nên tôi chấp nhận và tiếp tục dùng
Tôi thắc mắc liệu bạn xem đây là ngoài phạm vi của Zod, hay đơn giản là chưa có thời gian triển khai. Thảo luận liên quan nằm ở https://github.com/colinhacks/zod/discussions/2134
3.25.0thì nghe có vẻ hơi vô lýTôi đã dùng bản alpha của Zod trong vài tháng và chỉ muốn sửa
package.jsonđể nâng cấp, nhưng giờ có vẻ tôi phải lục lại toàn bộ lịch sử gitTôi rất biết ơn dự án này, nhưng riêng phản hồi này thì có vẻ các bạn đã làm nó khó hơn mức cần thiết. Tôi nghĩ có lẽ có thể phát hành cả 4.x cùng với
3.xNội dung “để đơn giản hóa việc migration, Zod 4 được phân phối cùng Zod 3 như một phần của bản phát hành
zod@3.25, và được import từ subpath"/v4"” trông như dấu hiệu cho thấy quản lý dependency của npm đang hoàn toàn rối tungPeer dependency hỏng đến mức v4 phải giả vờ là v3
Đúng là npm không quản lý tốt tình huống mà Zod đang gặp. Tuy nhiên Zod bị ràng buộc bởi việc gần như không nhận thư viện nào. Hàng chục đến hàng trăm thư viện import trực tiếp interface/class từ
"zod"và dùng chúng trong API công khai của mìnhNhững thư viện như vậy phải phát hành phiên bản major mới mỗi khi Zod tăng major, và với Zod điều đó có thể gây ra trận lở tuyết phiên bản khiến mọi người đều khổ sở. Nói thật, tôi đã nghĩ rằng phần lớn hệ sinh thái sẽ bị kẹt mãi ở v3
Vì vậy, tương tự Go, chúng tôi chọn cách thêm subpath mới thay vì phát hành phiên bản package mới cho mỗi lần phát hành phá vỡ tương thích. Trong hệ sinh thái TypeScript, chỉ với một peer dependency
zod@^3.25.0, có thể hỗ trợ đồng thời"zod/v3"và"zod/v4"Tức là refactor từng chỗ sử dụng sang
import ... from 'zod/v4', rồi khi xong thì nâng hẳn lên v4Ngược lại, npm còn có nhiều lối thoát hơn vì khi cần có thể chạy đồng thời nhiều phiên bản, hoặc ghi đè có chọn lọc một phần của đồ thị dependency bắc cầu
Hệ thống quản lý package nào giải quyết được vấn đề này? Ngay cả các nền tảng “ổn định” như Maven cũng xử lý kiểu vấn đề này bằng cách phát hành phiên bản dưới namespace mới, như khi Apache Commons chuyển từ v2 sang v3
Có một câu hỏi tôi đã thắc mắc từ lâu. Tôi nghe nói Zod có thể phù hợp với việc này, nhưng đọc tài liệu vẫn không rõ phải làm thế nào
Giả sử API máy chủ trả về các kiểu tinh vi hơn những gì nó có thể biểu diễn. Ví dụ
api/:postid/authortrả về User, nhưng có thể là User thông thường hoặc User ẩn danh, nên các trường nhưusername,locationcó thể là null. Trong trường hợp này, có thể bạn sẽ muốn biểu diễn đối tượng User bằng discriminated unionCác đối tượng đến từ endpoint khác cũng có thể cần chuyển đổi kiểu. User đôi khi có thể bao gồm
Post[], và nếu Post là bài viết của moderator thì cũng có thể có thuộc tính đặc biệtTrước đây tôi từng viết các hàm như
normalizeUser()vànormalizePost(), nhưng rất nhanh trở nên lộn xộn. Mỗi endpoint trả về một tập con khác nhau của model User/Post, khiến tôi phải tạo chừng 5 hàmnormalizePost, quá rối. Tôi tò mò thường thì vấn đề kiểu này được giải quyết thế nàoTức là tách các đối tượng
successvàfaileddựa trên một trường phân biệt nhưstatus. Nếu có nhiều thuộc tính đặc biệt cho moderator nhưng bạn không muốn liệt kê hoặc kiểm tra tất cả, bạn có thể định nghĩa hành vi cho phép đi quaDù nhiều method có schema khác nhau, nếu có phần chung thì hãy tạo schema đối tượng dùng chung, rồi tạo các đối tượng bổ sung thêm trường lên đó. Nếu có nhiều khả năng thì vẫn sẽ lộn xộn, nhưng nếu tình hình vốn đã lộn xộn thì validator ít nhất có thể kiểm chứng được sự lộn xộn đó
Nếu không phải full-stack TypeScript, chẳng hạn backend Python, có thể định nghĩa nhiều dạng
Userbằng Pydantic model và union, rồi tạo kiểu TypeScript cho client thông qua việc sinh schema OpenAPI/GraphQL và code generation"user_type"vào mọi kiểu trong union thì sẽ dễ xử lý trường hợp thường và trường hợp đặc biệt hơnVí dụ, nếu kiểm tra
user.user_type === 'authenticated', hệ thống kiểu sẽ biết rằng sau đó có thể dùnguser.nameCác thư viện TypeScript cho truy vấn GraphQL có thể suy luận động dạng phản hồi từ hình dạng các trường đã chọn. Nếu chọn
{ user { username posts { text } } }thì kiểu phản hồi sẽ cóposts, còn nếu chỉ chọn{ user { username } }thì thuộc tínhpostssẽ hoàn toàn vắng mặtMáy chủ biết dữ liệu mình gửi, nên phải cung cấp thông tin đó cho client dưới dạng metadata. Trên thực tế, có thể là backend Python dùng schema Pydantic, dựa vào đó tự động tạo đặc tả OpenAPI, rồi client sinh kiểu từ đó
Zod tốt hơn hẳn các lựa chọn thay thế tôi từng thấy, nhưng đôi khi chính việc cần kiểm chứng tường minh như thế này lại khiến tôi cảm thấy đó là một thất bại về việc phát triển web hiện đại đã đi đến đâu
Trong phát triển full-stack, việc phải mô tả cùng một hình dạng theo nhiều cách thật quá bực bội. Cuối cùng cần kiểm chứng input JS, Swagger để định nghĩa API, kiểm chứng input phía máy chủ, ORM để đảm bảo phù hợp schema, rồi cả các định nghĩa TypeScript riêng cho server và client, rất nhàm chán
TypeScript có vẻ như là single source of truth tốt nhất mà chúng ta có, nhưng thực tế các công cụ thử reflection lại tự định nghĩa lại model và builder của riêng mình. Chỉ riêng các lĩnh vực lớn lấy reflection làm cốt lõi đã có 5 mảng, mỗi mảng lại có nhiều cách triển khai
Công cụ phát TypeScript type cũ là
reflect-metadatacung cấp một phần thông tin kiểu ở runtime, nhưng nó nhắm tới đặc tả decorator và metadata rất cũ: https://www.npmjs.com/package/reflect-metadataCó lẽ chúng ta đang ở giai đoạn đầu của sự hợp nhất. Dự án Standard Schema dường như được phần lớn các thư viện kiểm chứng lớn hỗ trợ. Tuy vậy, việc mở rộng nó sang định nghĩa API hay công cụ ORM vẫn còn rất sơ khai
https://github.com/standard-schema/standard-schema?tab=readm...
Chỉ cần thay đổi một lần trong schema Zod là nó lan ra toàn bộ ứng dụng cùng với kiểm tra kiểu. Schema Zod trở thành single source of truth
Nếu đã có JSON Schema/Swagger schema thì cứ sinh Zod từ đó. Nếu dùng TypeScript ORM thì gần như chắc chắn sẽ có generator cho Zod
Thành thật mà nói, Zod được dùng rộng đến mức với tôi nó trở thành định nghĩa schema thống nhất mà những phần khác trong stack có thể phụ thuộc vào. Vì định nghĩa kiểu trực tiếp nên các developer thực sự giữ nó luôn cập nhật. Tài liệu Swagger của công ty thì luôn tụt hậu so với thay đổi
Trường hợp giữ nguyên hiện trạng là ổn chỉ tồn tại khi làm việc với khách hàng và nhà tuyển dụng chỉ muốn kết quả, không quan tâm cách làm. Trong bối cảnh đó, những tầng phức tạp đáng buồn này ít nhất cũng giúp tăng số giờ có thể tính phí
Tất nhiên với tiền đề rằng Zod là thư viện định nghĩa schema và kiểm chứng TypeScript mà họ đã chọn
Zod 4 trông có vẻ tốt, nhưng ngay cả khi tính cả các cải tiến mới nhất thì ArkType vẫn nhanh hơn nhiều lần, ở mức một chữ số
Vì tương thích ngược và tương thích cú pháp, đôi khi rất khó làm cho nó nhanh hơn nhiều như một thư viện khởi đầu hoàn toàn mới. Gần đây tôi đã phân tích tất cả các công cụ này trong một dự án và chọn ArkType một phần vì lý do đó. Ngoài ra cảm giác dùng TypeScript cũng tốt hơn
Chúng tôi chỉ dùng Zod để kiểm tra form nên tôi nghĩ “vì sao chuyện này lại quan trọng?”. Có phải có trường hợp mọi người kiểm tra những thứ như thông điệp đầu vào API thông lượng cao, khiến hiệu năng quan trọng hơn không
Dù vậy có lẽ tôi sẽ không chuyển khỏi Zod
Chúc mừng đội Zod với bản phát hành mới. Dù có nguy cơ nghe quá tiêu cực, tôi vẫn rùng mình khi nghĩ đến số lượng thay đổi phá vỡ tương thích được ghi trong hướng dẫn migration
Nếu là một dự án phụ thuộc nhiều vào Zod, đây có vẻ sẽ là một công việc nặng nề, đòi hỏi nhiều sự tập trung và thời gian của lập trình viên. Tôi đặc biệt đồng cảm vì từng bảo trì vài dự án frontend 4–5 năm tuổi ở công ty
Các dự án React lớn thường phụ thuộc vào nhiều thư viện, và mỗi khi từng thư viện đưa ra thay đổi lớn, lại còn thiếu tài liệu, mọi thứ rất nhanh trở nên quá tải. Đây là một trong những phần tôi ghét nhất khi làm việc với JavaScript, và việc giữ cho mọi thứ khớp nhau để tiếp tục chạy trơn tru giống như một con dốc leo mãi không hết
Thành thật mà nói đó là ác mộng, và tôi đã nghĩ giá mà làm bằng Django thì tốt hơn. Trái với dự đoán, migration Tailwind 3 → 4 thuộc nhóm đau đớn nhất
miniriêng. Việc migration dần dần mà không động đến package manager trở nên dễ hơnNgười dùng không quan tâm đến bản
minithì không cần để ý phần đó. Tuy nhiên lợi ích tree-shaking của bảnminiquá lớn, đến mức đang kích thích phát triển các lựa chọn thay thế, và Zod phải chấp nhận điều đó hoặc suy thoáiLà một full-stack developer tự vận hành một SaaS có hàng nghìn người dùng trong production, đôi khi tôi thấy khá dễ chịu khi nhận ra có biết bao vấn đề mà mình hoàn toàn không biết đến vì đã quyết định không làm SPA và không dùng framework frontend JS
Tôi thậm chí chưa từng nghĩ mình cần những thứ như Zod/ArkType, đây là lần đầu nghe đến và cũng sẽ không dùng
Tôi ngạc nhiên vì có quá nhiều công sức, độ phức tạp và công cụ được đưa vào việc xây SPA. Khi quyết định không làm SPA, cả một nhóm vấn đề nhất định đơn giản là không tồn tại. Thay vào đó, dùng trình duyệt đúng như cách ban đầu nó được thiết kế, với tải lại toàn trang và trọng tâm là phát triển backend, rồi thỉnh thoảng thêm tính phản ứng bằng các framework chỉ dành cho backend như Laravel Livewire
Mọi thứ từ kiểm soát truy cập đến kiểm tra dữ liệu, quản lý trạng thái đều đơn giản. Ứng dụng nhanh, responsive, hiện đại, thân thiện SEO và đang phục vụ hàng nghìn người trong production
Rốt cuộc thì schema nằm ở đâu đó. Nó có thể được định nghĩa trong hệ thống cơ sở dữ liệu, hoặc trong model ORM. Nhưng trong dự án lớn, đặt schema trong hệ thống cơ sở dữ liệu hoặc ORM có thể tạo ra những vấn đề rất khó, nên chúng tôi dùng Zod và Protobuf. Tôi nghĩ Protobuf cũng có thể được thay thế hoàn toàn bằng Zod hoặc thứ tương tự
Vụ bê bối Post Office ở Anh có liên quan đến một hệ thống IT tên Horizon: https://en.wikipedia.org/wiki/British_Post_Office_scandal
Sau khi đọc chi tiết, tôi nghĩ nếu có kiểm tra schema như Zod thì có lẽ đã góp phần ngăn vụ bê bối này. Phụ lục kỹ thuật trong tài liệu tòa án của vụ kiện tập thể cũng nhắc đến việc thiếu sử dụng schema: https://en.wikipedia.org/wiki/Bates_%26_Others_v_Post_Office...
Nghe như hiện tại bạn đang phòng thủ bằng cách viết rất nhiều câu lệnh
if. Tệ hơn nữa là có thể chỉ dựa vào kiểm tra form phía client của HTMLTôi không phải chuyên gia nên nói hơi thận trọng, nhưng tôi nghĩ JSON Schema có thể là một lựa chọn tốt vì nó dựa trên schema, nên có thể triển khai trình xác thực cả trong các ngôn ngữ không phải TypeScript
https://ajv.js.org là một trong những thư viện JSON Schema như vậy. Tôi tò mò không biết so với Zod thì thế nào
Nếu muốn, cũng có thể dùng nó như một bộ chuyển đổi JSON. Ví dụ, bạn có thể viết một schema nhận vào chuỗi, xác thực xem đó có phải chuỗi ngày ISO hay không, rồi xuất ra đối tượng
DateKhác biệt quan trọng là tiền xử lý và
refine. Trong Zod, bạn có thể cung cấp callback trước khi xác thực, điều này rất hữu ích nhưng không thể biểu diễn bằng JSON. Ví dụ, việc đổiMM/DD/YYYYthànhDD/MM/YYYYtrước khi xác thực ngày tháng hữu ích thường xuyên hơn bạn tưởngKhi xác thực, có thể dùng AJV hoặc hệ thống xác thực schema của chính TypeBox. Cái sau nhanh hơn nhiều nhưng chỉ hỗ trợ đồng bộ, còn AJV có các tùy chọn xác thực bất đồng bộ như kiểm tra cơ sở dữ liệu
Tôi ngạc nhiên trước các phản ứng tiêu cực xung quanh chủ đề này
Tôi đã thử nghiệm phiên bản đầu của Zod v4 và thích API mới, nhưng rất lo lắng không biết lộ trình migration sẽ ra sao. Tôi thậm chí đã định đề xuất phát hành dưới một tên package hoàn toàn mới
Tuy nhiên, cách tiếp cận của tác giả rất khôn ngoan. Nó cho phép những người như tôi áp dụng v4 ngay lập tức mà không cần chờ mọi dependency được cập nhật
Tôi vừa bắt đầu đưa Zod vào một dự án mới, và không thể có thời điểm nào tốt hơn
Dựa trên những gì thấy hiện tại, có vẻ nếu chuyển sang v4 thì đã phải thay đổi rất nhiều thứ