HardPro challengePythonJavaScriptTypeScript
Type-safe Builder Pattern
TypeScriptTypesPatterns
The Builder pattern constructs complex objects step-by-step. In TypeScript, you can make it type-safe so that calling .build() without required fields is a compile error:
// The trick: use a generic type parameter to track which fields are set
class Builder<TSet extends string = never> {
method(m: HttpMethod): Builder<TSet | 'method'> { ... }
url(u: string): Builder<TSet | 'url'> { ... }
// 'this' parameter — TypeScript checks the call site, not the implementation
build(this: Builder<TSet & ('method' | 'url')>): RequestConfig { ... }
}
new RequestBuilder()
.method('GET')
.url('/api/challenges')
.build(); // ✅
new RequestBuilder()
.method('GET')
.build(); // ❌ TypeScript Error: Property 'url' is missing in type 'Builder<"method">'Implement RequestBuilder
| Method | Behavior |
|---|---|
.method(m) | Sets HTTP method |
.url(u) | Sets request URL |
.header(key, value) | Adds a header (chainable, multiple calls) |
.body(b) | Sets request body |
.build() | Returns the final RequestConfig object |
.method() and .url() are required before .build(). The TypeScript constraint is in the this parameter of build().
Sample tests
Test #1minimal GET request
Input: [[["method","GET"],["url","https://api.example.com/challenges"],["build"]]]
Output: {"url":"https://api.example.com/challenges","method":"GET","headers":{}}
Test #2POST request with body
Input: [[["method","POST"],["url","https://api.example.com/submit"],["body",{"code":"fn(){}"}],["build"]]]
Output: {"url":"https://api.example.com/submit","body":{"code":"fn(){}"},"method":"POST","headers":{}}
Test #3request with multiple headers
Input: [[["method","GET"],["url","/api"],["header","Authorization","Bearer token123"],["header","Accept","application/json"],["build"]]]
Output: {"url":"/api","method":"GET","headers":{"Accept":"application/json","Authorization":"Bearer token123"}}