Skip to content
Development
Skill

/typescript

TypeScript strict mode with eslint and jest

From plugin
maggy
71073 skills1 agent25 commands1 hook

Claude Code

$ npx -y skills add alinaqi/maggy --skill typescript --agent claude-code

SKILL.md

typescript.SKILL.md
name: typescript
description: TypeScript strict mode with eslint and jest
when-to-use: When working on TypeScript files
user-invocable: false
paths: ["**/*.ts", "**/*.tsx", "tsconfig*.json"]
effort: medium

TypeScript Skill

---

Strict Mode (Non-Negotiable)

// tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

---

Project Structure

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.md

---

Tooling (Required)

// package.json scripts
{
  "scripts": {
    "lint": "eslint src/ --ext .ts,.tsx",
    "typecheck": "tsc --noEmit",
    "test": "jest",
    "test:coverage": "jest --coverage",
    "format": "prettier --write 'src/**/*.ts'"
  }
}
// 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],
    }
  }
);

---

Testing with Jest

// 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();
  });
});

---

GitHub Actions

name: 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}}'

---

Pre-Commit Hooks

Using Husky + lint-staged:

npm install -D husky lint-staged
npx husky init
// package.json
{
  "lint-staged": {
    "*.{ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ]
  }
}
# .husky/pre-commit
npx lint-staged
npx tsc --noEmit
npm run test -- --onlyChanged --passWithNoTests

This runs on every commit: 1. ESLint + Prettier on staged files 2. Type check entire project 3. Tests for changed files only

---

Type Patterns

Discriminated Unions for Results

type Result<T> =
  | { ok: true; value: T }
  | { ok: false; error: string };

function parseUser(data: unknown): Result<User> {
  // Type-safe error handling without exceptions
}

Branded Types for IDs

type 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 { ... }

Const Assertions for Literals

const STATUSES = ['pending', 'active', 'closed'] as const;
type Status = typeof STATUSES[number]; // 'pending' | 'active' | 'closed'

Zod for Runtime Validation

import { z } from 'zod';

const UserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
});

type User = z.infer<typeof UserSchema>;

---

TypeScript Anti-Patterns

  • ❌ `any` type - use `unknown` and narrow
  • ❌ Type assertions (`as`) - use type guards
  • ❌ Non-null assertions (`!`) - handle null explicitly
  • ❌ `@ts-ignore` without explanation
  • ❌ Enums - use const objects or union types
  • ❌ Classes for data - use interfaces/types
  • ❌ Default exports - use named exports
Read more
@alinaqi
Ships withmaggy

Turn Claude Code into a self-reviewing, test-enforced engineering system that remembers context across sessions — then route work across 13 models from a single dashboard.

71073 skills1 agent
Get the whole plugin

Stars on GitHub

Momentum

stars in total
710
Star history of alinaqi/maggy on GitHub, a chart by star-history.com

Other skills on maggy.

aeo-optimization

aeo-optimization

AI Engine Optimization - semantic triples, page templates, content clusters for AI citations

@alinaqi@alinaqiInstall Skill
agent-teams

agent-teams

Claude Code Agent Teams - default team-based development with strict TDD pipeline enforcement

@alinaqi@alinaqiInstall Skill
ai-models

ai-models

Latest AI models reference - Claude, OpenAI, Gemini, Eleven Labs, Replicate

@alinaqi@alinaqiInstall Skill
android-kotlin

android-kotlin

Android Kotlin development with Coroutines, Jetpack Compose, Hilt, and MockK testing

@alinaqi@alinaqiInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about typescript.

Which coding agents can use typescript?
typescript installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.