askill
typescript-type-safe-api-contracts

typescript-type-safe-api-contractsSafety 100Repository

TypeScript patterns for type-safe API contracts, strict typing, Zod integration. Use when designing APIs, creating types, validating data. Keywords: "api design", "schema", "type safety", "interface", "zod", "validation", "type", "strict mode".

0 stars
1.2k downloads
Updated 2/5/2026

Package Files

Loading files...
SKILL.md

TypeScript Type-Safe API Contracts

Core Principle: Explicit Return Types (Mandatory)

// ❌ BAD: Implicit return type
export function getUser(id: string) {
  return db.user.findUnique({ where: { id } });
}

// ✅ GOOD: Explicit return type
export async function getUser(id: string): Promise<User | null> {
  return db.user.findUnique({ where: { id } });
}

Interface vs Type

Use interface for object shapes:

interface User {
  id: string;
  name: string;
  email: string;
}

interface ApiResponse<T> {
  success: boolean;
  data: T;
}

Use type for unions, intersections, utilities:

type Status = 'pending' | 'active' | 'archived';

type ApiResult<T> =
  | { success: true; data: T }
  | { success: false; error: string };

Generic API Response Wrapper

// types/api/common.ts
export type ApiResponse<T> =
  | ApiSuccessResponse<T>
  | ApiErrorResponse;

export interface ApiSuccessResponse<T> {
  success: true;
  data: T;
}

export interface ApiErrorResponse {
  success: false;
  error: {
    code: string;
    message: string;
    details?: Record<string, string[]>;
  };
}

// Usage
export async function createUser(data: CreateUserInput): Promise<ApiResponse<User>> {
  // ...
}

Zod Integration (Runtime Validation)

import { z } from 'zod';

// 1. Define Zod schema
const userSchema = z.object({
  name: z.string().min(1, 'Name required').max(100),
  email: z.string().email('Invalid email'),
  age: z.number().int().positive().optional(),
});

// 2. Infer TypeScript type from schema
export type User = z.infer<typeof userSchema>;

// 3. Validate at runtime
export async function createUser(input: unknown): Promise<ApiResponse<User>> {
  try {
    const validated = userSchema.parse(input); // Throws if invalid
    // ...
  } catch (error) {
    if (error instanceof z.ZodError) {
      return {
        success: false,
        error: {
          code: 'VALIDATION_ERROR',
          message: 'Invalid input',
          details: error.flatten().fieldErrors,
        },
      };
    }
  }
}

Utility Types for Transformations

interface User {
  id: string;
  name: string;
  email: string;
  password: string;
}

// Pick specific fields
type PublicUser = Pick<User, 'id' | 'name'>; // { id: string; name: string }

// Omit fields
type UserWithoutPassword = Omit<User, 'password'>; // { id: string; name: string; email: string }

// Make all fields optional
type PartialUser = Partial<User>; // { id?: string; name?: string; ... }

// Make all fields required
type RequiredUser = Required<Partial<User>>;

// Create record type
type UserMap = Record<string, User>; // { [key: string]: User }

Anti-Patterns

Using any (FORBIDDEN):

// ❌ BAD
function processData(data: any) { }

// ✅ GOOD
function processData(data: unknown) {
  if (typeof data === 'string') {
    // Type narrowing
  }
}

Non-null assertion without guards:

// ❌ BAD
const user = getUser()!; // Assumes non-null, can crash

// ✅ GOOD
const user = getUser();
if (!user) return;
// Now TypeScript knows user is non-null

For backend synchronization and Python/Pydantic mapping, see /api-contract command.

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

95/100Analyzed 2/13/2026

An excellent, high-density technical reference for TypeScript API patterns. It provides clear 'Good vs Bad' examples, integrates runtime validation with Zod, and covers essential utility types. Highly actionable for coding assistants.

100
95
95
90
95

Metadata

Licenseunknown
Version-
Updated2/5/2026
Publishermajiayu000

Tags

api