Loading skill
Install any skill in seconds. Free to start, no credit card required.
Get Started Free →TypeScript strict mode with eslint and jest
.claude/skills/alinaqi-typescript/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 4% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 64% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 32% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 52% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 9% | 0% |
json// tsconfig.json { "compilerOptions": { "strict": true, "noImplicitAny": true, "strictNullChecks": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true } }
project/
├── src/
│ ├── core/ # Pure business logic
│ │ ├── types.ts # Domain types/interfaces
│ │ ├── services/ # Pure functions
│ │ └── index.ts # Public API
│ ├── infra/ # Side effects
│ │ ├── api/ # HTTP handlers
│ │ ├── db/ # Database operations
│ │ └── external/ # Third-party integrations
│ └── utils/ # Shared utilities
├── tests/
│ ├── unit/
│ └── integration/
├── package.json
├── tsconfig.json
└── CLAUDE.mdjson// package.json scripts { "scripts": { "lint": "eslint src/ --ext .ts,.tsx", "typecheck": "tsc --noEmit", "test": "jest", "test:coverage": "jest --coverage", "format": "prettier --write 'src/**/*.ts'" } }
javascript// eslint.config.js import eslint from '@eslint/js'; import tseslint from 'typescript-eslint'; export default tseslint.config( eslint.configs.recommended, ...tseslint.configs.strictTypeChecked, { rules: { '@typescript-eslint/no-explicit-any': 'error', '@typescript-eslint/explicit-function-return-type': 'error', 'max-lines-per-function': ['error', 20], 'max-depth': ['error', 2], 'max-params': ['error', 3], } } );
typescript// tests/unit/services/user.test.ts import { calculateTotal } from '../../../src/core/services/pricing'; describe('calculateTotal', () => { it('returns sum of item prices', () => { // Arrange const items = [{ price: 10 }, { price: 20 }]; // Act const result = calculateTotal(items); // Assert expect(result).toBe(30); }); it('returns zero for empty array', () => { expect(calculateTotal([])).toBe(0); }); it('throws on invalid item', () => { expect(() => calculateTotal([{ invalid: 'item' }])).toThrow(); }); });
yamlname: TypeScript Quality Gate on: [push, pull_request] jobs: quality: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Lint run: npm run lint - name: Type Check run: npm run typecheck - name: Test with Coverage run: npm run test:coverage - name: Coverage Threshold (80%) run: npm run test:coverage -- --coverageThreshold='{"global":{"branches":80,"functions":80,"lines":80,"statements":80}}'
Using Husky + lint-staged:
bashnpm install -D husky lint-staged npx husky init
json// package.json { "lint-staged": { "*.{ts,tsx}": [ "eslint --fix", "prettier --write" ] } }
bash# .husky/pre-commit npx lint-staged npx tsc --noEmit npm run test -- --onlyChanged --passWithNoTests
This runs on every commit:
typescripttype Result<T> = | { ok: true; value: T } | { ok: false; error: string }; function parseUser(data: unknown): Result<User> { // Type-safe error handling without exceptions }
typescripttype UserId = string & { readonly brand: unique symbol }; type OrderId = string & { readonly brand: unique symbol }; // Can't accidentally pass UserId where OrderId expected function getOrder(orderId: OrderId): Order { ... }
typescriptconst STATUSES = ['pending', 'active', 'closed'] as const; type Status = typeof STATUSES[number]; // 'pending' | 'active' | 'closed'
typescriptimport { z } from 'zod'; const UserSchema = z.object({ email: z.string().email(), name: z.string().min(1).max(100), }); type User = z.infer<typeof UserSchema>;
any type - use unknown and narrowas) - use type guards!) - handle null explicitly@ts-ignore without explanationOther measured skills in the registry, with their headline benchmark lift.