API ReferenceCore API
createContract
API reference for the createContract function.
Overview
createContract is the primary function for defining your API contract. It accepts a contract definition and returns it with full type inference.
Import
import { createContract } from '@ts-contract/core';Signature
function createContract<C extends ContractDef>(contract: C): CType Parameters
- C - The contract definition type, inferred from the argument
Parameters
- contract - An object defining your API routes and nested contracts
Returns
The same contract object with full TypeScript type information
Usage
Basic Contract
import { createContract } from '@ts-contract/core';
import { z } from 'zod';
const contract = createContract({
getUser: {
method: 'GET',
path: '/users/:id',
pathParams: z.object({ id: z.string() }),
responses: {
200: z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
}),
404: z.object({ message: z.string() }),
},
},
});Related Types
ContractDef
The type for a contract definition:
interface ContractDef {
[key: string]: RouteDef | WebSocketDef | ContractDef;
}A contract is an object where each value is either:
- A
RouteDef(route definition) - A
WebSocketDef(WebSocket definition) - Another
ContractDef(nested contract)
RouteDef
The type for a route definition:
type RouteDef = {
method: Method;
path: string;
pathParams?: SchemaProtocol<any>;
query?: SchemaProtocol<any>;
headers?: Record<string, SchemaProtocol<any>>;
body?: SchemaProtocol<any>;
responses: Partial<Record<HttpStatusCodes, SchemaProtocol<any>>>;
summary?: string;
metadata?: Record<string, string | number | boolean>;
};Required fields:
method- HTTP method (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)path- URL path template with optional:paramplaceholdersresponses- Object mapping status codes to response schemas
Optional fields:
pathParams- Schema for path parametersquery- Schema for query string parametersheaders- Object mapping header names to schemasbody- Schema for request bodysummary- Human-readable descriptionmetadata- Custom key-value pairs
Method
type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD';HttpStatusCodes
type HttpStatusCodes =
| 100 | 101 | 102
| 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226
| 300 | 301 | 302 | 303 | 304 | 305 | 307 | 308
| 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409
| 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419
| 420 | 421 | 422 | 423 | 424 | 428 | 429 | 431 | 451
| 500 | 501 | 502 | 503 | 504 | 505 | 507 | 511;Examples
With Metadata
const contract = createContract({
getUser: {
method: 'GET',
path: '/users/:id',
pathParams: z.object({ id: z.string() }),
responses: {
200: z.object({ id: z.string(), name: z.string() }),
},
summary: 'Retrieve a user by ID',
metadata: {
requiresAuth: true,
rateLimit: 100,
version: 'v1',
},
},
});With All Fields
const contract = createContract({
updateUser: {
method: 'PUT',
path: '/users/:id',
pathParams: z.object({ id: z.string() }),
query: z.object({ notify: z.boolean().optional() }),
headers: {
'authorization': z.string(),
'x-api-version': z.string(),
},
body: z.object({
name: z.string(),
email: z.string().email(),
}),
responses: {
200: z.object({
id: z.string(),
name: z.string(),
email: z.string(),
updatedAt: z.string(),
}),
400: z.object({ message: z.string() }),
401: z.object({ message: z.string() }),
404: z.object({ message: z.string() }),
},
summary: 'Update a user profile',
metadata: {
requiresAuth: true,
},
},
});Best Practices
Export Contracts
Export your contract for use throughout your application:
// contract.ts
export const contract = createContract({
getUser: { /* ... */ },
createUser: { /* ... */ },
});// Other files
import { contract } from './contract';Use Shared Schemas
Extract common schemas to avoid duplication:
const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
});
const ErrorSchema = z.object({ message: z.string() });
const contract = createContract({
getUser: {
method: 'GET',
path: '/users/:id',
pathParams: z.object({ id: z.string() }),
responses: {
200: UserSchema,
404: ErrorSchema,
},
},
createUser: {
method: 'POST',
path: '/users',
body: UserSchema.omit({ id: true }),
responses: {
201: UserSchema,
400: ErrorSchema,
},
},
});Organize by Resource
Group related routes together:
const contract = createContract({
users: {
list: { /* ... */ },
get: { /* ... */ },
create: { /* ... */ },
update: { /* ... */ },
delete: { /* ... */ },
},
posts: {
list: { /* ... */ },
get: { /* ... */ },
create: { /* ... */ },
},
});See Also
- initContract - Initialize a contract with plugins
- Type Helpers - Extract types from contracts
- Contracts Guide - Learn about contract organization
- Routes & Schemas - Route definition details