Auto-Generate TypeScript APIs from Thrift Definitions
This article explains how to use Thrift as an interface definition language to automatically generate TypeScript client code, covering the definition syntax, annotation for request mapping, code generation architecture, and practical examples that boost frontend development efficiency.
Background
If a single interface definition can be used by both frontend and backend to generate code, communication overhead is reduced and development efficiency improves. ByteDance internally uses Thrift for RPC definitions, and these definitions can also serve as frontend API contracts.
Interface Definition
Thrift, a cross-language RPC framework, can be treated directly as an interface definition language. A simple Thrift example looks like this:
namespace go namesapce
// Request struct
struct GetRandomRequest {
1: optional i32 min,
2: optional i32 max,
3: optional string extra
}
// Response struct
struct GetRandomResponse {
1: optional i64 random_num
}
// Service definition
service RandomService {
GetRandomResponse GetRandom (1: GetRandomRequest req)
}Annotations can specify additional RESTful details such as query parameters, body parameters, and the HTTP path:
namespace go namesapce
struct GetRandomRequest {
1: optional i32 min (api.source = "query"),
2: optional i32 max (api.source = "query"),
3: optional string extra (api.source = "body")
}
struct GetRandomResponse {
1: optional i64 random_num,
}
service RandomService {
GetRandomResponse GetRandom (1: GetRandomRequest req) (api.get = "/api/get-random"),
}The api.source annotation indicates where a parameter comes from (query or body), and api.get defines the endpoint path and HTTP method.
Generate Typescript
From the annotated Thrift definition, the corresponding TypeScript client can be generated automatically:
interface GetRandomRequest {
min: number;
max: number;
extra: string;
}
interface GetRandomResponse {
random_num: number;
}
async function GetRandom(req: GetRandomRequest): Promise<GetRandomResponse> {
return request<GetRandomResponse>({
url: '/api/get-random',
method: 'GET',
query: {
min: req.min,
max: req.max,
},
body: {
extra: req.extra,
}
});
}Developers can call GetRandom directly without worrying about the generated code's details.
Architecture Design
The core architecture for Thrift‑based code generation consists of converting Thrift files into an intermediate representation (IR) such as JSON, then applying plugins to produce target code. A typical IR JSON structure might be:
{
"name": "GetRandom",
"method": "get",
"path": "/api/get-random",
"req_schema": {
"query_params": [
{"name": "min", "type": "int", "optional": true},
{"name": "max", "type": "int", "optional": true}
],
"body_params": [
{"name": "extra", "type": "string", "optional": true}
],
"header_params": []
},
"resp_schema": {
"header_params": [],
"body_params": []
}
}PrePlugins handle the conversion from Thrift to IR, while PostPlugins generate the final code. Different PostPlugins can emit TypeScript, Go, or other languages, keeping the architecture extensible.
Summary
Thrift can serve as a concrete interface definition language; if it doesn’t fit your needs, you can design a custom IDL. Using a shared definition reduces front‑back communication costs, and automated code generation improves code quality and development speed. Further exploration includes parsing strategies, multi‑file linking, naming conventions, runtime type checking, and integration with request libraries such as useRequest or React Query.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
