language-patterns
Scannednpx machina-cli add skill sequenzia/agent-alchemy/language-patterns --openclawLanguage Patterns
This skill provides language-specific patterns and best practices. Apply patterns that match the project's language and framework.
TypeScript Patterns
Type Safety
Use strict types over any:
// Bad
function process(data: any): any {
return data.value;
}
// Good
interface DataItem {
value: string;
count: number;
}
function process(data: DataItem): string {
return data.value;
}
Use discriminated unions for variants:
type Result<T> =
| { success: true; data: T }
| { success: false; error: Error };
function handleResult<T>(result: Result<T>) {
if (result.success) {
// TypeScript knows result.data exists
console.log(result.data);
} else {
// TypeScript knows result.error exists
console.error(result.error);
}
}
Use unknown over any for external data:
async function fetchData(): Promise<unknown> {
const response = await fetch('/api/data');
return response.json();
}
// Then validate/parse
const data = await fetchData();
if (isValidData(data)) {
// Now safely typed
}
Null Handling
Use optional chaining and nullish coalescing:
// Optional chaining
const userName = user?.profile?.name;
// Nullish coalescing (only for null/undefined)
const displayName = userName ?? 'Anonymous';
// Combine them
const city = user?.address?.city ?? 'Unknown';
Use type guards:
function isUser(obj: unknown): obj is User {
return (
typeof obj === 'object' &&
obj !== null &&
'id' in obj &&
'email' in obj
);
}
Async Patterns
Prefer async/await over raw promises:
// Good
async function fetchUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`Failed to fetch user: ${response.status}`);
}
return response.json();
}
Handle errors properly:
async function safeOperation(): Promise<Result<Data>> {
try {
const data = await riskyOperation();
return { success: true, data };
} catch (error) {
return { success: false, error: error as Error };
}
}
Parallel operations:
// Run in parallel
const [users, posts] = await Promise.all([
fetchUsers(),
fetchPosts()
]);
// With error handling
const results = await Promise.allSettled([
fetchUsers(),
fetchPosts()
]);
Python Patterns
Type Hints
Use type hints for clarity:
from typing import Optional, List, Dict
def process_users(
users: List[dict],
filter_active: bool = True
) -> List[str]:
"""Process users and return their names."""
result: List[str] = []
for user in users:
if filter_active and not user.get("active"):
continue
result.append(user["name"])
return result
Use dataclasses for data containers:
from dataclasses import dataclass
from typing import Optional
@dataclass
class User:
id: int
email: str
name: str
active: bool = True
profile: Optional[dict] = None
Use Pydantic for validation:
from pydantic import BaseModel, EmailStr
class UserCreate(BaseModel):
email: EmailStr
name: str
age: int
class Config:
extra = "forbid" # Reject unknown fields
Pythonic Patterns
Use comprehensions:
# List comprehension
names = [user.name for user in users if user.active]
# Dict comprehension
user_map = {user.id: user for user in users}
# Generator for large data
active_users = (user for user in users if user.active)
Context managers for resources:
# File handling
with open("file.txt", "r") as f:
content = f.read()
# Database connections
with get_db_connection() as conn:
conn.execute(query)
# Custom context manager
from contextlib import contextmanager
@contextmanager
def timer(name: str):
start = time.time()
yield
print(f"{name}: {time.time() - start:.2f}s")
Use pathlib for paths:
from pathlib import Path
config_path = Path(__file__).parent / "config" / "settings.yaml"
if config_path.exists():
content = config_path.read_text()
Error Handling
class ValidationError(Exception):
"""Raised when input validation fails."""
pass
class NotFoundError(Exception):
"""Raised when a resource is not found."""
pass
def get_user(user_id: int) -> User:
user = db.query(User).get(user_id)
if user is None:
raise NotFoundError(f"User {user_id} not found")
return user
React Patterns
Component Patterns
Functional components with hooks:
interface UserCardProps {
user: User;
onEdit: (user: User) => void;
}
function UserCard({ user, onEdit }: UserCardProps) {
const handleClick = useCallback(() => {
onEdit(user);
}, [user, onEdit]);
return (
<div className="user-card">
<h3>{user.name}</h3>
<button onClick={handleClick}>Edit</button>
</div>
);
}
Custom hooks for logic reuse:
function useUser(userId: string) {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
setLoading(true);
fetchUser(userId)
.then(setUser)
.catch(setError)
.finally(() => setLoading(false));
}, [userId]);
return { user, loading, error };
}
State Management
Use appropriate state level:
// Local state - component only
const [isOpen, setIsOpen] = useState(false);
// Lifted state - shared between siblings
// Put in common parent
// Context - deeply nested sharing
const ThemeContext = createContext<Theme>("light");
// External store - complex app state
// Use Redux, Zustand, or similar
Derive state when possible:
// Bad: redundant state
const [items, setItems] = useState<Item[]>([]);
const [totalCount, setTotalCount] = useState(0);
// Good: derive from source of truth
const [items, setItems] = useState<Item[]>([]);
const totalCount = items.length;
Performance
Memoization:
// Memoize expensive computations
const sortedItems = useMemo(
() => items.sort((a, b) => a.name.localeCompare(b.name)),
[items]
);
// Memoize callbacks passed to children
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);
// Memoize components
const MemoizedChild = memo(ChildComponent);
Lazy loading:
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
);
}
Error Boundaries
class ErrorBoundary extends Component<Props, State> {
state = { hasError: false, error: null };
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
componentDidCatch(error: Error, info: ErrorInfo) {
logError(error, info);
}
render() {
if (this.state.hasError) {
return <ErrorFallback error={this.state.error} />;
}
return this.props.children;
}
}
General Best Practices
Naming Conventions
| Language | Variables | Functions | Classes | Constants |
|---|---|---|---|---|
| TypeScript | camelCase | camelCase | PascalCase | UPPER_SNAKE |
| Python | snake_case | snake_case | PascalCase | UPPER_SNAKE |
| React | camelCase | camelCase/use* | PascalCase | UPPER_SNAKE |
File Organization
TypeScript/React:
src/
components/
Button/
Button.tsx
Button.test.tsx
index.ts
hooks/
utils/
types/
Python:
src/
package/
__init__.py
models.py
services.py
utils.py
tests/
test_models.py
test_services.py
Import Organization
TypeScript:
// 1. External packages
import React from 'react';
import { useState } from 'react';
// 2. Internal modules (absolute)
import { Button } from '@/components';
import { useAuth } from '@/hooks';
// 3. Relative imports
import { helper } from './utils';
import type { Props } from './types';
Python:
# 1. Standard library
import os
from pathlib import Path
# 2. Third-party packages
import requests
from pydantic import BaseModel
# 3. Local imports
from .models import User
from .utils import helper
Source
git clone https://github.com/sequenzia/agent-alchemy/blob/main/claude/core-tools/skills/language-patterns/SKILL.mdView on GitHub Overview
This skill codifies language-specific patterns and best practices for TypeScript, Python, and React. It guides developers to apply idioms like strict TypeScript typing, discriminated unions, optional chaining, and Python dataclasses and Pydantic for robust code. Use it to align features with the project's language and framework.
How This Skill Works
Patterns are organized by language and area (TypeScript, Python, React), each with concrete examples and recommended practices. Developers apply the relevant patterns to their feature implementation, leveraging type hints, guards, and validation to ensure safe, maintainable code across the stack.
When to Use It
- Implement a TypeScript feature that benefits from strict typing and safe external data handling
- Validate and parse external data in TS with unknown and type guards
- Handle async operations in TS with async/await and proper error handling
- Define Python data models with type hints, dataclasses, or Pydantic for validation
- Write Pythonic code using comprehensions and context managers for resources
Quick Start
- Step 1: Identify your project language (TypeScript, Python, or React) and the pattern you need.
- Step 2: Replace unsafe constructs with strict types or type hints; add a guard/validation.
- Step 3: Validate behavior with a quick runtime check or test to ensure correctness.
Best Practices
- Use strict types over any in TypeScript to improve safety
- Prefer unknown over any for untrusted input and validate before use
- Use discriminated unions to model variants and enable exhaustive checks
- Leverage optional chaining and nullish coalescing for clean null handling
- In Python, prefer dataclasses or Pydantic for clear data models and validation
Example Use Cases
- TypeScript: define Result<T> as a discriminated union and handle both branches
- TypeScript: fetchData returns unknown and isValidData validates before use
- TypeScript: demonstrate parallel operations with Promise.all and Promise.allSettled
- Python: use @dataclass for User with id, email, name, and an optional profile
- Python: use Pydantic's BaseModel for validation with extra = 'forbid'