Loading...
Loading...
TypeScript/JavaScript project workflow guidelines using Bun package manager. Triggers on `.ts`, `.tsx`, `bun`, `package.json`, TypeScript. Covers bun run, bun install, bun add, tsconfig.json patterns, ESM/CommonJS modules, type safety, Biome formatting, naming conventions (PascalCase, camelCase, UPPER_SNAKE_CASE), project structure, error handling, environment variables, async patterns, and code quality tools. Activate when working with TypeScript files (.ts, .tsx), JavaScript files (.js, .jsx), Bun projects, tsconfig.json, package.json, bun.lock, or Bun-specific tooling.
npx skill4agent add ilude/claude-code-config typescript-workflow| Task | Tool | Command |
|---|---|---|
| Lint + Format | Biome | |
| Type check | tsc | |
| Dead code | ts-prune | |
| Test | Bun test | |
| Coverage | c8 | |
# Package management
bun install # Install dependencies from package.json
bun add <package> # Add production dependency
bun add --dev <package> # Add development dependency
bun remove <package> # Remove dependency
# Running code and scripts
bun run <script> # Run script defined in package.json
bun <file.ts> # Run TypeScript/JavaScript directly
bun run build # Run build script
# Testing
bun test # Run tests with Bun's native test runner
# Package info
bun list # List installed packages
bun outdated # Check for updates// Import named exports
import { UserService } from './services/user-service';
import { type User } from './types';
// Import default exports
import express from 'express';
// Import with alias
import * as helpers from './utils/helpers';
// Export named
export function getUserById(id: string): Promise<User> {
// ...
}
// Export default
export default UserService;
// Re-export
export { type User } from './types';
export { UserService } from './services/user-service';// Require imports
const { UserService } = require('./services/user-service');
const express = require('express');
// Module exports
module.exports = UserService;
module.exports = { UserService, UserRepository };package.json{
"type": "module",
"name": "my-app",
"version": "1.0.0"
}{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020"],
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"allowJs": false,
"outDir": "./dist",
"rootDir": "./src",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@services/*": ["src/services/*"],
"@models/*": ["src/models/*"]
},
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"removeComments": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}bun add --dev @biomejs/biomebiome.json{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"organizeImports": {
"enabled": true
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noUselessSwitchCase": "error"
},
"style": {
"noNonNullAssertion": "warn"
}
}
},
"javascript": {
"formatter": {
"semicolons": "always",
"quoteStyle": "single",
"trailingCommas": "es5"
}
}
}# Check and fix all issues
bun run biome check --apply .
# Format only
bun run biome format --write .
# Lint only
bun run biome lint .
# CI mode (check without fixing)
bun run biome check .# ESLint
bun add --dev eslint
bun run eslint src/ --fix
# Prettier
bun add --dev prettier
bun run prettier --write src/UserProfile.tsxLoginForm.tsxformatDate.tsapiClient.tsUser.tsApiResponse.tsAPI_ENDPOINTS.tsCONFIG.ts.test.ts.spec.tsuser.service.test.ts// Classes/Types/Interfaces/Enums: PascalCase
class UserService { /* ... */ }
interface UserRepository { /* ... */ }
enum UserRole { Admin = 'ADMIN', User = 'USER' }
// Methods, properties, variables, functions: camelCase
getUserById(id: string): Promise<User>
const userData = {};
// Private members: camelCase with leading underscore
private _cache: Map<string, User> = new Map();
// Constants: UPPER_SNAKE_CASE
const MAX_RETRIES = 3;
const API_BASE_URL = 'https://api.example.com';
// React hooks: camelCase with use prefix
function useUserData(userId: string) { /* ... */ }anyunknownanynoImplicitAny// Function parameters and return types
function processUser(user: User): Promise<ProcessedUser> {
// ...
}
// Arrow functions
const formatName = (first: string, last: string): string => {
return `${first} ${last}`;
};
// Complex types
type ApiResponse<T> = {
status: number;
data: T;
error?: string;
};
interface RequestHandler {
handle(request: Request): Promise<Response>;
}// Generic functions
function getById<T extends { id: string }>(items: T[], id: string): T | undefined {
return items.find((item) => item.id === id);
}
// Generic classes
class Repository<T> {
async getById(id: string): Promise<T | null> {
// ...
}
}
// Generic types
type Result<T, E = Error> = { success: true; data: T } | { success: false; error: E };import { z } from 'zod';
// Schema definition
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().positive().optional(),
});
// Type inference from schema
type User = z.infer<typeof UserSchema>;
// Runtime validation
function createUser(data: unknown): User {
return UserSchema.parse(data);
}
// Safe parsing with error handling
const result = UserSchema.safeParse(data);
if (!result.success) {
console.error(result.error.format());
}project/
├── src/
│ ├── main.ts # Entry point
│ ├── types/ # Type definitions
│ ├── services/ # Business logic
│ ├── repositories/ # Data access layer
│ ├── models/ # Data models
│ ├── handlers/ # Request/event handlers
│ ├── middleware/ # Express/web middleware
│ ├── utils/ # Utility functions
│ └── config/ # Configuration
├── tests/ # Unit and integration tests
├── dist/ # Compiled output (gitignored)
├── package.json
├── tsconfig.json
├── biome.json
└── bun.lock// Absolute imports with path aliases
import { UserService } from '@services/user-service';
import type { User } from '@models/user';
// Relative imports within same feature
import { UserRepository } from '../repositories/user-repository';
import { validateUser } from '../utils/validators';
// Re-exports from index files
export { UserService, UserRepository } from './index';// Define custom error classes
class AppError extends Error {
constructor(message: string, public code: string, public statusCode = 500) {
super(message);
this.name = 'AppError';
}
}
class ValidationError extends AppError {
constructor(message: string, public field: string) {
super(message, 'VALIDATION_ERROR', 400);
}
}
class NotFoundError extends AppError {
constructor(message: string) {
super(message, 'NOT_FOUND', 404);
}
}
// Result pattern for explicit error handling
type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
async function safeFetchUser(id: string): Promise<Result<User, AppError>> {
try {
const user = await getUser(id);
return { ok: true, value: user };
} catch (error) {
return { ok: false, error: error instanceof AppError ? error : new AppError('Unknown', 'UNKNOWN') };
}
}// env.ts
import { z } from 'zod';
const EnvSchema = z.object({
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
PORT: z.coerce.number().default(3000),
DATABASE_URL: z.string().url(),
API_KEY: z.string(),
});
export default EnvSchema.parse(process.env);// Async/await with error handling
async function fetchUserData(id: string): Promise<User> {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) throw new Error('Failed to fetch');
return response.json();
} catch (error) {
console.error('Error fetching user:', error);
throw error;
}
}
// Concurrent operations with Promise.all
async function loadDashboardData(): Promise<DashboardData> {
const [users, products, stats] = await Promise.all([
fetchUsers(),
fetchProducts(),
fetchStats(),
]);
return { users, products, stats };
}import { describe, it, expect, beforeEach } from 'bun:test';
import { UserService } from '@services/user-service';
describe('UserService', () => {
let service: UserService;
beforeEach(() => {
service = new UserService();
});
it('should fetch user by id', async () => {
const user = await service.getById('123');
expect(user).toBeDefined();
expect(user?.id).toBe('123');
});
});anyunknown"strict": truenextjs-workflowreact-workflowdatabase-workflow.claude/CLAUDE.md