Tan Phat Media

GraphQL Schema to TypeScript

Dán GraphQL SDL, nhận ngay interface và type TypeScript tương ứng

Bộ đọc SDL viết riêng chạy trong trình duyệt, không gửi schema của bạn đi đâu

GraphQL SDL
TypeScript
// Type TypeScript sinh tự động từ GraphQL SDL.
// Nguồn duy nhất của sự thật vẫn là file schema, sửa schema rồi sinh lại thay vì sửa tay ở đây.

/**
 * Người dùng đã đăng ký trong hệ thống.
 * Mỗi người dùng gắn với một hồ sơ công khai.
 * Cài đặt interface GraphQL: Node
 */
export interface User {
  id: string;
  /** Tên hiển thị, luôn có giá trị */
  name: string;
  bio: string | null;
  role: Role;
  posts: Post[];
  avatar: string | null;
  createdAt: string;
  /** @deprecated Dùng name thay thế */
  legacyName: string | null;
}

export interface Node {
  id: string;
}

/**
 * Bài viết do người dùng tạo
 * Cài đặt interface GraphQL: Node
 */
export interface Post {
  id: string;
  title: string;
  body: string | null;
  tags: string[] | null;
  author: User;
  publishedAt: string | null;
}

/** Cài đặt interface GraphQL: Node */
export interface Comment {
  id: string;
  content: string;
  author: User;
}

/** Kết quả tìm kiếm có thể là người dùng, bài viết hoặc bình luận */
export type SearchResult =
  | User
  | Post
  | Comment;

/** Vai trò quyết định quyền hạn */
export type Role =
  | "ADMIN"
  | "EDITOR"
  | "MEMBER";

export interface CreatePostInput {
  title: string;
  body?: string | null;
  tags?: string[] | null;
  authorId: string;
}

export interface Query {
  me: User | null;
  user: User | null;
  posts: Post[];
  search: SearchResult[];
}

export interface Mutation {
  createPost: Post;
  deletePost: boolean;
}
Tùy chọn sinh code

Viết theo dạng TenScalar = KieuTypeScript. Scalar khai báo trong SDL mà không có trong bảng này sẽ được sinh thành một type alias riêng dùng kiểu mặc định ở trên, để bạn sửa một chỗ là xong.

Schema có gì

Object type

5

Input type

1

Interface

1

Union

1

Enum

1

Scalar

2

Directive

1

Tổng số trường

28

File kết quả dài 76 dòng.

Quy tắc chuyển đổi công cụ đang áp dụng

Nullable ngược với TypeScript. Trong GraphQL mọi kiểu đều cho phép null trừ khi có dấu chấm than. Vì vậy bio: String ra bio: string | null, còn id: ID! ra id: string.

List lồng nhau đọc từ trong ra ngoài. [Post!]! ra Post[], [Post] ra Array<Post | null> | null. Khi phần tử có dấu gạch đứng, công cụ đổi sang dạng Array để không phải đặt ngoặc.

Scalar dựng sẵn. ID và String thành string, Int và Float thành number, Boolean thành boolean. Mọi scalar khác lấy từ bảng ánh xạ, không có trong bảng thì thành type alias riêng.

Union và enum. Union GraphQL thành union type TypeScript giữa các thành viên. Enum có hai lối ra: union chuỗi nhẹ hơn cho bundle, còn enum TypeScript cho phép tham chiếu bằng tên.

Directive. Khai báo directive được đọc để không làm hỏng bộ đọc nhưng không sinh type. Riêng @deprecated trên trường và giá trị enum được giữ lại thành ghi chú JSDoc.

Công cụ này khác gì các công cụ liên quan

Trang này chỉ làm một việc: đọc phần khai báo schema và sinh type. Nó không gọi endpoint, không chạy query và không kiểm tra dữ liệu trả về có khớp schema hay không.

  • GraphQL Playground — nơi chạy query và mutation thật với endpoint của bạn. Trang đó làm việc với dữ liệu chạy được, trang này làm việc với phần mô tả kiểu.
  • JSON to TypeScript — khi bạn chỉ có một mẫu JSON trả về mà không có schema. Type suy ra từ mẫu nên có thể sai chỗ nullable, còn ở đây nullable lấy đúng theo dấu chấm than trong SDL.
  • OpenAPI Spec Generator — dành cho API REST. Nếu hệ thống của bạn có cả REST lẫn GraphQL thì dùng hai trang song song, mỗi trang cho một nửa.
  • HAR File Analyzer — khi lớp type đã đúng mà trang vẫn chậm, hãy xuất file HAR từ tab Network để xem request GraphQL nào đang tốn thời gian nhất.
Không gửi schema lên máy chủ
Không cần cài codegen
Chạy được với schema dán một phần

Hợp tác ngay với Tấn Phát Digital

Chúng tôi không chỉ thiết kế website, mà còn giúp doanh nghiệp xây dựng thương hiệu số mạnh mẽ. Cung cấp dịch vụ thiết kế website trọn gói từ thiết kế đến tối ưu SEO. Hãy liên hệ ngay với Tấn Phát Digital để cùng tạo nên những giải pháp công nghệ đột phá, hiệu quả và bền vững cho doanh nghiệp của bạn tại Hồ Chí Minh.

Chuyển GraphQL SDL sang type TypeScript: nullable, list lồng nhau, enum và union đều đúng

Công cụ đọc trực tiếp phần khai báo schema GraphQL bạn dán vào, phân tích từng type, input, interface, union, enum, scalar và directive, rồi sinh ra interface cùng type TypeScript tương ứng. Bộ đọc SDL được viết riêng chạy trong trình duyệt nên schema của bạn không rời khỏi máy, và bạn không phải cài codegen chỉ để lấy vài chục dòng type.

Tính năng nổi bật

  • Bộ đọc SDL viết riêng, hiểu type, input, interface, union, enum, scalar và directive mà không cần thư viện ngoài
  • Dịch đúng dấu chấm than và dấu ngoặc vuông lồng nhau, kể cả trường hợp [[String]] hay [Post!]!
  • Sinh interface cho object type và input type, union type cho union GraphQL
  • Enum có hai lối ra: union chuỗi nhẹ cho bundle hoặc enum TypeScript tham chiếu được bằng tên
  • Bảng ánh xạ scalar tùy chỉnh sửa được ngay trên trang, mặc định DateTime thành string
  • Chọn kiểu nullable dạng T | null hoặc dạng Maybe<T> kèm helper tự thêm vào đầu file
  • Tùy chọn thêm trường __typename cho object type và interface
  • Giữ nguyên description trong SDL thành JSDoc, kể cả block string ba nháy kép và ghi chú @deprecated

Vì sao cần một trang chuyển SDL sang TypeScript thay vì gõ tay hoặc cài codegen

Có ba tình huống mà bộ sinh code cài trong dự án không giải quyết được gọn. Thứ nhất là khi bạn chỉ nhận được một mẩu schema qua tin nhắn hoặc trong tài liệu API của đối tác, chưa có endpoint để trỏ tới, chưa có quyền truy cập, mà vẫn cần dựng type để viết trước phần giao diện. Thứ hai là khi bạn đang rà soát một pull request có thay đổi schema và muốn thấy ngay phần TypeScript tương ứng sẽ trông thế nào, thay vì chạy lại toàn bộ quy trình sinh code chỉ để đọc một type. Thứ ba là khi dự án nhỏ, chỉ dùng vài query, việc kéo thêm một chuỗi gói phụ thuộc cùng file cấu hình cho bộ sinh code là quá nặng so với nhu cầu. Gõ tay thì được, nhưng lỗi thường gặp nhất lại là lỗi im lặng: quên rằng trường không có dấu chấm than nghĩa là nó có thể null, và thế là ứng dụng gặp lỗi khi máy chủ trả về null ở đúng chỗ bạn quên. Trang này giữ đúng quy tắc đó cho bạn.

Lợi ích khi sử dụng

  • Không phải cài thêm gói phụ thuộc nào chỉ để lấy vài chục dòng type
  • Không nhầm nullable, vì quy tắc dấu chấm than được áp dụng máy móc chứ không dựa vào trí nhớ
  • Description trong schema theo được sang code, đội phát triển đọc type là hiểu ngay ý nghĩa trường
  • Schema dán vào chỉ nằm trong trình duyệt, phù hợp cả với schema nội bộ chưa công bố
  • Đổi tùy chọn thấy kết quả ngay, tiện để so sánh hai quy ước trước khi chốt cho cả đội

Cách chuyển GraphQL schema sang TypeScript

  1. 1Dán phần SDL của bạn vào ô bên trái. Có thể dán toàn bộ file schema hoặc chỉ vài type đang quan tâm, công cụ vẫn chạy và sẽ cảnh báo những kiểu được tham chiếu mà chưa khai báo.
  2. 2Chọn kiểu nullable ở phần tùy chọn. Chọn T | null nếu bạn muốn đọc thẳng, chọn Maybe<T> nếu dự án đã quen với quy ước của các bộ sinh code phổ biến.
  3. 3Chọn cách sinh enum. Union chuỗi cho ra bundle nhẹ hơn và so sánh bằng chuỗi tự nhiên, enum TypeScript cho phép tham chiếu bằng tên và tự động gợi ý khi gõ.
  4. 4Sửa bảng ánh xạ scalar nếu dự án của bạn dùng scalar riêng. Mỗi dòng viết theo dạng tên scalar, dấu bằng, rồi kiểu TypeScript tương ứng.
  5. 5Đọc phần cảnh báo nếu có, chép code bằng nút chép hoặc tải về tệp schema.types.ts rồi đưa vào thư mục type của dự án.

Quy tắc nullable của GraphQL ngược với thói quen của người viết TypeScript

Đây là nguồn gốc của phần lớn lỗi khi chuyển đổi bằng tay. Trong TypeScript, khi bạn viết một trường có kiểu string thì mặc định nó luôn có giá trị, muốn cho phép null bạn phải nói rõ. GraphQL làm ngược lại hoàn toàn: mọi kiểu đều cho phép null, chỉ khi thêm dấu chấm than phía sau thì trường mới bắt buộc có giá trị. Nghĩa là một trường viết là bio kiểu String trong schema, nếu chuyển thẳng thành string trong TypeScript, sẽ nói dối trình biên dịch. Máy chủ hoàn toàn có quyền trả về null cho trường đó và ứng dụng sẽ hỏng ở dòng gọi phương thức trên giá trị null, còn trình biên dịch thì không cảnh báo được vì đã bị bảo rằng trường luôn có chuỗi. Điều làm quy tắc này khó nhớ hơn là GraphQL còn cho phép null có nghĩa khác nhau tùy vị trí trong danh sách. Một trường kiểu danh sách có thể null ở mức cả danh sách, ở mức từng phần tử, hoặc cả hai, và mỗi tổ hợp cho ra một kiểu TypeScript khác nhau. Công cụ này đọc từng lớp bọc từ trong ra ngoài nên không bị nhầm, và đó cũng là lý do nên để máy làm phần này.

Bốn tổ hợp của danh sách và cách chúng ra kiểu TypeScript

Một trường kiểu danh sách trong GraphQL có bốn dạng viết, và người mới rất dễ đọc lướt qua mà bỏ sót dấu. Dạng thứ nhất là danh sách bắt buộc chứa phần tử bắt buộc, viết là dấu ngoặc vuông bọc kiểu có chấm than rồi thêm chấm than ở ngoài. Kết quả là mảng thuần, ví dụ danh sách bài viết ra thành Post kèm cặp ngoặc vuông. Dạng thứ hai là danh sách bắt buộc nhưng phần tử có thể null, ra thành mảng mà mỗi phần tử là bài viết hoặc null. Dạng thứ ba là danh sách có thể null nhưng phần tử bắt buộc, ra thành mảng bài viết hoặc null ở mức ngoài cùng. Dạng thứ tư là cả hai đều có thể null, cho kiểu lồng hai lớp. Khi phần tử của mảng là một kiểu ghép có dấu gạch đứng, công cụ tự đổi sang cú pháp Array bọc ngoài thay vì cặp ngoặc vuông, vì viết ngoặc vuông sau một kiểu ghép sẽ cho ra kết quả sai nếu thiếu ngoặc đơn. Đây là lỗi kinh điển khi gõ tay: quên ngoặc đơn thì mảng bài viết hoặc null lại thành bài viết hoặc mảng null. Danh sách lồng nhiều tầng cũng được xử lý theo cùng nguyên tắc, đọc từ lớp trong cùng ra ngoài.

Scalar tùy chỉnh và lý do không nên để tất cả thành any

GraphQL chỉ định nghĩa sẵn năm scalar là ID, String, Int, Float và Boolean. Mọi kiểu nguyên thủy khác đều do dự án tự khai báo, phổ biến nhất là DateTime, Date, JSON, Upload, BigInt và URL. Vì tên scalar không nói gì về cách nó được tuần tự hóa, không có cách tự động nào biết chắc DateTime sẽ đến tay bạn dưới dạng chuỗi ISO hay số mili giây, nên phần ánh xạ này bắt buộc phải do người viết quyết định. Cách nhanh nhất là để tất cả thành any, nhưng làm vậy thì mọi lợi ích của việc sinh type biến mất đúng ở những chỗ dễ sai nhất. Trường thời gian mà thành any thì bạn có thể gọi phương thức của đối tượng ngày tháng lên một chuỗi mà không ai cảnh báo. Công cụ này mặc định để DateTime thành string vì đó là cách phổ biến nhất khi tuần tự hóa qua JSON, đồng thời cho bạn sửa cả bảng ánh xạ ngay trên trang. Scalar nào khai báo trong schema mà không có trong bảng sẽ được sinh thành một type alias riêng mang đúng tên scalar, dùng kiểu mặc định bạn chọn. Cách này giữ tên scalar hiện diện trong code để bạn thấy chỗ cần sửa, và khi cần đổi thì chỉ sửa một dòng alias thay vì tìm khắp file.

Union chuỗi hay enum TypeScript, và ảnh hưởng tới bundle

Một enum GraphQL có thể ra hai dạng trong TypeScript, và lựa chọn này ảnh hưởng thật tới sản phẩm cuối chứ không chỉ là chuyện sở thích. Union chuỗi là một type thuần, tồn tại duy nhất ở thời điểm biên dịch, nên sau khi biên dịch xong nó biến mất hoàn toàn và không thêm một byte nào vào bundle gửi tới trình duyệt. Bù lại, bạn phải viết đúng chính tả giá trị mỗi lần dùng, dù trình soạn thảo có gợi ý sẵn. Enum TypeScript thì ngược lại, nó sinh ra một đối tượng thật trong mã kết quả, tốn dung lượng và không bị loại bỏ khi dọn mã chết trong một số cấu hình, đổi lại bạn tham chiếu được bằng tên và khi đổi giá trị chuỗi ở một chỗ thì mọi nơi dùng tên đều theo. Với ứng dụng chạy trên trình duyệt và có nhiều enum, union chuỗi thường là lựa chọn hợp lý hơn. Với mã chạy trên máy chủ hoặc thư viện nội bộ nơi dung lượng không phải mối lo, enum TypeScript đọc dễ hơn. Điều quan trọng là cả đội chọn một quy ước rồi giữ nguyên, vì trộn hai kiểu trong cùng một dự án sẽ khiến người đọc phải kiểm tra lại mỗi lần gặp một enum mới.

Type sinh ra không thay thế được việc kiểm tra dữ liệu lúc chạy

Có một hiểu nhầm cần nói thẳng: type TypeScript chỉ tồn tại lúc biên dịch. Sau khi biên dịch, chúng biến mất và không còn gì kiểm tra dữ liệu thật đến từ mạng có khớp hay không. Nếu máy chủ triển khai sai so với schema, hoặc schema đã đổi mà bạn chưa sinh lại type, mã của bạn vẫn biên dịch trót lọt rồi hỏng lúc chạy. Điều này càng đáng lưu ý với GraphQL vì phản hồi có thể chứa đồng thời cả phần dữ liệu lẫn mảng lỗi, và khi một trường cho phép null gặp lỗi thì máy chủ trả null cho trường đó rồi ghi lỗi vào mảng riêng, còn khi một trường bắt buộc gặp lỗi thì null lan ngược lên trường cha gần nhất cho phép null. Nghĩa là một trường bạn khai là bắt buộc vẫn có thể vắng mặt trong phản hồi thực tế nếu trường cha bị null hóa. Cách làm an toàn là dùng type sinh ra cho phần lớn công việc, nhưng ở ranh giới nhận dữ liệu từ mạng thì thêm một lớp kiểm tra lúc chạy cho các trường quan trọng, và luôn xử lý cả mảng lỗi trong phản hồi chứ không chỉ đọc phần dữ liệu.

Câu hỏi thường gặp (FAQ)

Công cụ có gửi schema của tôi lên máy chủ không?

Không. Toàn bộ việc đọc SDL và sinh code chạy bằng JavaScript ngay trong trình duyệt của bạn. Không có lời gọi mạng nào, không lưu lại nội dung bạn dán vào. Đóng tab là mọi thứ biến mất, nên dùng được với cả schema nội bộ chưa công bố.

Vì sao trường String lại ra string | null mà không phải string?

Vì trong GraphQL mọi kiểu đều cho phép null trừ khi có dấu chấm than phía sau. Trường String không có chấm than nghĩa là máy chủ được phép trả về null. Nếu chuyển thẳng thành string thì trình biên dịch sẽ không cảnh báo bạn ở đúng chỗ dễ hỏng nhất.

Có cần dán nguyên cả file schema không hay dán một phần cũng được?

Dán một phần vẫn chạy. Những kiểu được tham chiếu mà chưa khai báo sẽ vẫn xuất hiện trong code với đúng tên của chúng, đồng thời hiện một dòng cảnh báo để bạn biết cần dán bổ sung. Cách này tiện khi bạn chỉ quan tâm vài type.

Nên chọn T | null hay Maybe<T>?

Hai dạng tương đương về ý nghĩa. Chọn T | null nếu bạn muốn đọc code không cần biết thêm quy ước nào. Chọn Maybe<T> nếu dự án đã quen với đầu ra của các bộ sinh code phổ biến, khi đó công cụ tự thêm dòng khai báo Maybe ở đầu file cho bạn.

Enum nên sinh thành union chuỗi hay enum TypeScript?

Union chuỗi biến mất hoàn toàn sau khi biên dịch nên không thêm dung lượng vào bundle, phù hợp với ứng dụng chạy trên trình duyệt. Enum TypeScript sinh ra một đối tượng thật, tốn dung lượng nhưng cho phép tham chiếu bằng tên. Quan trọng nhất là cả đội chọn một kiểu rồi giữ nguyên.

Scalar DateTime của tôi trả về số mili giây chứ không phải chuỗi, sửa ở đâu?

Sửa trong bảng ánh xạ scalar ngay dưới phần tùy chọn. Đổi dòng DateTime thành number, kết quả cập nhật ngay. Bảng này nhận mọi biểu thức kiểu TypeScript hợp lệ, kể cả kiểu ghép hay tên type bạn tự khai báo ở nơi khác.

Trường __typename có nên bật không?

Bật khi bạn cần phân biệt các thành viên của một union hoặc interface lúc chạy, vì đó là cách chuẩn để biết đối tượng nhận được thuộc kiểu nào. Nếu không dùng tới, để tắt cho code gọn. Trường này được sinh ở dạng tùy chọn nên không bắt buộc phải truy vấn.

Directive trong schema có được chuyển thành gì không?

Khai báo directive được đọc để bộ phân tích không bị lỗi, nhưng không sinh ra type vì directive là chỉ dẫn cho quá trình thực thi chứ không mô tả hình dạng dữ liệu. Riêng directive đánh dấu trường không nên dùng nữa thì được giữ lại thành ghi chú trong JSDoc.

Vì sao [Post] lại ra Array<Post | null> | null trông rối như vậy?

Vì cả danh sách lẫn từng phần tử đều không có dấu chấm than, nghĩa là cả hai đều có thể null. Kiểu trông rối chính là mô tả trung thực những gì schema cho phép. Nếu bạn muốn kiểu gọn hơn, hãy sửa schema thành danh sách bắt buộc chứa phần tử bắt buộc.

Type sinh ra có bảo đảm dữ liệu trả về đúng như vậy không?

Không. Type chỉ tồn tại lúc biên dịch rồi biến mất, nên không có gì kiểm tra dữ liệu thật từ mạng. Nếu máy chủ triển khai lệch schema hoặc schema đã đổi mà bạn chưa sinh lại, mã vẫn biên dịch được nhưng hỏng lúc chạy. Nên thêm lớp kiểm tra ở ranh giới nhận dữ liệu.

Công cụ có sinh type cho query và mutation tôi viết không?

Không. Trang này chỉ đọc phần khai báo schema, tức là hình dạng đầy đủ của dữ liệu. Type cho từng query cụ thể phải suy ra từ đúng những trường bạn chọn trong tài liệu truy vấn, đó là việc của bộ sinh code chạy trong dự án và cần cả file truy vấn lẫn schema.

Có tùy chọn nào sinh interface cho tham số của field không?

Có, bật công tắc sinh interface cho tham số của field. Mỗi field có tham số sẽ được thêm một interface đặt tên theo kiểu tên type ghép với tên field và hậu tố Args. Tham số không bắt buộc được đánh dấu tùy chọn theo đúng quy tắc nullable của GraphQL.

Từ khóa liên quan

  • chuyển graphql schema sang typescript
  • graphql sdl to typescript
  • sinh type từ graphql schema
  • graphql codegen online
  • graphql schema to typescript interface
  • chuyển đổi sdl graphql
  • graphql nullable typescript
  • graphql maybe type
  • graphql enum typescript
  • graphql union typescript
  • custom scalar graphql typescript
  • datetime scalar graphql
  • graphql __typename typescript
  • graphql input type typescript
  • graphql interface typescript
  • graphql list not null typescript
  • công cụ graphql cho developer
  • tạo type graphql không cần cài codegen
  • graphql schema parser online
  • graphql deprecated jsdoc

Công cụ Developer Tools liên quan

.env Generator

Tạo file .env và .env.example cho dự án.

.gitignore Generator

Tạo .gitignore cho Node.js, Python, Java.

API Mock Generator

Tạo mock JSON data cho API testing.

API Response Formatter

Format và phân tích API response.

API Tester

Test REST API: GET, POST, PUT, DELETE.

Postman Alternative - API Testing Tool Online với Collections, Environment & File Upload

Postman Alternative miễn phí - Test APIs với Collections, Multiple Environments, Pre-request Scripts, Collection Runner, File Upload (form-data), Tests/Assertions, Code Generation (cURL, JS, Python, Node.js). Browser-based, không cần cài đặt. Save requests, export/import collections, auto-save history. Hỗ trợ Bearer Token, Basic Auth, API Key. Hoàn hảo cho API development và testing.

Swagger API Tester - Test API với OpenAPI/Swagger Spec & Authentication Online

Swagger API Tester miễn phí - Import OpenAPI/Swagger specification và test API endpoints với đầy đủ authentication (Bearer Token/JWT, Basic Auth, API Key). Hỗ trợ OpenAPI 3.0, Swagger 2.0, auto-parse endpoints, parameters, request body. Giao diện như Swagger UI với color-coded methods, grouped endpoints, real-time testing. Hoàn hảo cho API development, testing, debugging secured APIs.

Base Converter

Chuyển đổi Binary, Hex, Base32.

Base64 Encoder

Mã hóa/giải mã Base64.

Binary Converter

Chuyển đổi Decimal, Binary, Hex.

Box Shadow Generator

Tạo CSS box-shadow trực quan.

Chmod Calculator

Tính quyền file Linux.

Dịch vụ của Tấn Phát Digital

Đang xây sản phẩm và cần thêm người làm phần nặng?

Gói giải pháp doanh nghiệp

Nền tảng custom cho ngân hàng, y tế và sàn B2B, chuẩn ISO 27001, GDPR, PCI-DSS, SLA 99.99%.

Từ 50.000.000đXem chi tiết →

Dịch vụ phát triển Blockchain & Web3

Smart contract, dApp và NFT marketplace đa chuỗi, audit bảo mật đầy đủ trước khi lên mainnet.

Từ 50.000.000đXem chi tiết →

Dịch vụ thiết kế website tại Hồ Chí Minh

Website doanh nghiệp, bán hàng và đặt lịch, chuẩn SEO ngay từ cấu trúc, tốc độ tải dưới 3 giây.

Từ 5.000.000đXem chi tiết →

Dịch vụ thiết kế landing page

Trang đích riêng cho từng chiến dịch quảng cáo, tỷ lệ chuyển đổi 3–8%, bàn giao trong 5–21 ngày.

Từ 3.000.000đXem chi tiết →

Tư vấn và báo giá miễn phí trong 24 giờ. Xem toàn bộ dịch vụ

Zalo
Facebook
Tấn Phát Digital
Zalo
Facebook