Nỗi ám ảnh mang tên ‘OpenAPI thủ công’
Viết file openapi.yaml dài 3.000 dòng bằng tay là cách nhanh nhất để bào mòn lòng kiên nhẫn của một lập trình viên. Nếu bạn từng quên cập nhật một field trong hàng chục endpoint, bạn sẽ hiểu cảm giác “râu ông nọ cắm cằm bà kia” khi Frontend gọi API mà dữ liệu trả về không đúng như tài liệu. Cú pháp YAML rườm rà, lặp đi lặp lại và cực kỳ khó tái sử dụng schema là những rào cản lớn trong các dự án microservices phức tạp.
Sau 6 tháng đưa TypeSpec vào môi trường production, mình nhận ra đây chính là “cứu cánh” cho quy trình API-first. Thay vì hì hục gõ YAML, mình viết code với cú pháp tinh gọn như TypeScript. Công cụ này tự động render mọi thứ từ Swagger đến Client SDK. Thực tế tại team mình, TypeSpec đã giúp cắt giảm tới 70% thời gian hội ý về cấu trúc dữ liệu giữa Backend và Frontend.
TypeSpec: Khi TypeScript và API Design “về chung một nhà”
TypeSpec là ngôn ngữ định nghĩa dịch vụ (IDL) do Microsoft phát triển. Bạn có thể coi nó là phiên bản TypeScript dành riêng cho việc thiết kế API. Nó cho phép bạn định nghĩa model, endpoint và các ràng buộc dữ liệu chỉ với vài dòng code súc tích.
Sức mạnh lớn nhất của TypeSpec nằm ở khả năng tạo ra Single Source of Truth. Từ một file .tsp duy nhất, bạn có thể xuất ra hàng loạt định dạng khác nhau:
- OpenAPI 3.0/3.1 cho tài liệu Swagger.
- JSON Schema để validate dữ liệu đầu vào.
- Client SDK cho đa ngôn ngữ (C#, Java, Python, TypeScript).
- Protobuf dành cho các hệ thống sử dụng gRPC.
Thực hành: Xây dựng API đầu tiên trong 5 phút
Để bắt đầu, hãy đảm bảo bạn đã cài NodeJS. Việc cài đặt TypeSpec compiler chỉ tốn một câu lệnh npm:
npm install -g @typespec/compiler
Tiếp theo, hãy khởi tạo dự án mới:
mkdir my-api-design && cd my-api-design
tsp init
Khi được hỏi, bạn hãy chọn template @typespec/openapi3. Đây là lựa chọn phổ biến nhất để tạo tài liệu API chuẩn hóa.
Viết code TypeSpec thay vì gõ YAML
Hãy thử thiết kế một API quản lý bài viết. Bạn sẽ thấy cú pháp của TypeSpec rõ ràng và mạch lạc hơn hẳn so với mớ ngoặc nhọn của JSON:
import "@typespec/http";
import "@typespec/rest";
import "@typespec/openapi3";
using TypeSpec.Http;
using TypeSpec.Rest;
@service({
title: "Blog Service",
})
@server("https://api.itfromzero.com", "Production server")
namespace Blog;
model Post {
@visibility("read")
id: string;
@minLength(5)
title: string;
content: string;
status: "draft" | "published";
createdAt: utcDateTime;
}
@route("/posts")
interface Posts {
@get list(): Post[];
@post create(@body post: Post): Post | { @statusCode statusCode: 400, message: string };
@get read(@path id: string): Post | { @statusCode statusCode: 404 };
}
Đoạn code trên định nghĩa một model Post kèm theo các validation như @minLength. Interface Posts chứa các method HTTP tương ứng. Bạn không còn phải lo lắng về khoảng trắng (indentation) khó chịu như trong YAML nữa.
Tự động hóa việc xuất tài liệu
Khi thiết kế xong, bạn chỉ cần chạy lệnh sau để có ngay file openapi.yaml chuyên nghiệp:
tsp compile .
Kết quả sẽ xuất hiện trong thư mục tsp-output. Trong lúc làm việc, nếu cần format nhanh dữ liệu hoặc kiểm tra JSON, mình thường dùng toolcraft.app. Công cụ này giúp xử lý nhanh các đoạn JSON kết quả mà không làm nặng máy như khi cài quá nhiều extension vào VS Code.
Giải quyết nỗi lo “lệch pha” với Client SDK
Rắc rối thường xảy ra khi Backend thay đổi một field nhưng Frontend không hay biết. Với TypeSpec, bạn có thể dùng các Emitter để tự động generate code cho frontend.
Cài đặt emitter cho TypeScript rất đơn giản:
npm install @azure-tools/typespec-ts
Sau đó, hãy cấu hình trong file tspconfig.yaml. Khi bạn compile, TypeSpec sẽ tạo ra toàn bộ interface và hàm gọi API. Team Frontend chỉ cần import package này là có ngay IntelliSense gợi ý code chuẩn xác. Sai sót do gõ nhầm tên field lúc này gần như bằng không.
Bài học xương máu từ dự án thực tế
Sau nửa năm áp dụng, mình rút ra 3 kinh nghiệm quan trọng để tối ưu quy trình:
- Đừng để tài liệu “câm nín”: Hãy dùng decorator
@docđể mô tả chi tiết từng field. Những dòng mô tả này sẽ xuất hiện trực tiếp trên Swagger UI, giúp các dev khác hiểu API mà không cần hỏi bạn. - Module hóa mọi thứ: Hãy gom các model dùng chung như
ErrorResponsehayPaginationvào filecommon.tsp. Cách này giúp bạn quản lý hàng chục microservices mà không bị trùng lặp code. - Gắn CI/CD vào cuộc chơi: Hãy thiết lập để hệ thống tự động chạy
tsp compilemỗi khi có Pull Request. Nếu file.tsplỗi, build sẽ fail ngay lập tức, ngăn chặn việc đẩy tài liệu sai lên hệ thống.
Khả năng linting (kiểm tra lỗi) của TypeSpec thực sự rất đáng giá. Nếu bạn lỡ định nghĩa hai endpoint trùng route, compiler sẽ báo lỗi ngay. Bạn sẽ phát hiện ra sai sót ngay lúc viết code thay vì đợi đến khi deploy mới tá hỏa vì tài liệu bị loạn.
Lời kết
TypeSpec không đơn thuần là một công cụ mới, nó thay đổi hoàn toàn cách chúng ta tư duy về thiết kế hệ thống. Nó xóa bỏ khoảng cách giữa bản vẽ và thực thi. Dù dự án của bạn là startup nhỏ hay hệ thống enterprise, việc đầu tư vào TypeSpec sẽ giúp bạn rảnh tay hơn khi quy mô dự án phình to. Đừng tốn thời gian sửa file YAML thủ công nữa, hãy thử TypeSpec và cảm nhận sự khác biệt ngay hôm nay!

