文件预览

typescript-profile.md

查看 Code QC 技能包中的文件内容。

文件内容

references/typescript-profile.md

# TypeScript QC Profile

## Project Detection

TypeScript project if any of these exist:
- `tsconfig.json`
- `package.json` with TypeScript in dependencies
- `.ts` or `.tsx` files

## Monorepo Detection

Check for monorepo structure in order:

### pnpm Workspaces
```bash
if [ -f "pnpm-workspace.yaml" ]; then
    echo "pnpm monorepo detected"
    # List workspaces
    pnpm list --recursive --depth 0
fi
```

### npm/Yarn Workspaces
```bash
if grep -q '"workspaces"' package.json 2>/dev/null; then
    echo "npm/yarn workspaces detected"
    # List packages
    jq -r '.workspaces[]' package.json
fi
```

### Nx
```bash
if [ -f "nx.json" ]; then
    echo "Nx monorepo detected"
    # List projects
    npx nx show projects
fi
```

### Turborepo
```bash
if [ -f "turbo.json" ]; then
    echo "Turborepo detected"
    # List packages
    ls -d packages/*/package.json apps/*/package.json 2>/dev/null
fi
```

### Lerna (legacy)
```bash
if [ -f "lerna.json" ]; then
    echo "Lerna monorepo detected"
    npx lerna list
fi
```

### Monorepo QC Strategy

For monorepos, run QC per package or use workspace-aware commands:

```bash
# pnpm - run in all packages
pnpm -r run lint
pnpm -r run test

# Nx - run affected only
npx nx affected --target=lint
npx nx affected --target=test

# Turborepo
npx turbo run lint test

# Changed packages only (CI mode)
pnpm -r --filter "...[origin/main]" run test
```

## Test Runner Detection

Check in order:
1. `vitest.config.ts` or `vitest` in devDependencies → `npx vitest`
2. `jest.config.ts/js` or `jest` in devDependencies → `npx jest`
3. `package.json` → `scripts.test` → use that command
4. Fallback: `npm test`

### With Coverage
```bash
# Vitest
npx vitest --coverage

# Jest
npx jest --coverage --coverageReporters=json-summary

# Parse coverage
cat coverage/coverage-summary.json | jq '.total.lines.pct'
```

## Phase 3: Static Analysis with eslint

### Standard Check

Use project's eslint config if available:
```bash
npx eslint . --format json --output-file /tmp/eslint-report.json
```

If no eslint config exists:
```bash
npx eslint . --no-eslintrc \
  --parser @typescript-eslint/parser \
  --plugin @typescript-eslint \
  --rule '{"no-unused-vars":"warn","no-console":"warn","no-debugger":"error"}'
```

### Fix Mode
```bash
npx eslint . --fix
```

### Monorepo eslint
```bash
# Root config for shared rules
npx eslint . --config .eslintrc.js

# Or per-package
pnpm -r run lint

# Nx
npx nx run-many --target=lint --all
```

### Key Rules to Check

| Rule | What it catches |
|------|-----------------|
| `no-unused-vars` | Unused variables/imports |
| `no-console` | console.log in production code |
| `no-debugger` | debugger statements |
| `@typescript-eslint/no-explicit-any` | Untyped `any` usage |
| `@typescript-eslint/no-non-null-assertion` | Unsafe `!` assertions |
| `@typescript-eslint/strict-boolean-expressions` | Truthy/falsy bugs |

## Phase 3.5: Type Checking

```bash
# Full type check without emit
npx tsc --noEmit

# Specific project in monorepo
npx tsc --project packages/core/tsconfig.json --noEmit

# All projects (Nx)
npx nx run-many --target=typecheck --all

# Parse errors
npx tsc --noEmit 2>&1 | grep -c "error TS"
```

### Strict Mode Verification

Check if strict mode is enabled:
```bash
grep -q '"strict": true' tsconfig.json && echo "Strict mode enabled" || echo "Warning: strict mode disabled"
```

## Smoke Test Patterns

### API Endpoint (Express/Fastify)
```typescript
import request from 'supertest';
import { app } from './app';

async function smokeTestApi() {
  const res = await request(app).get('/health');
  if (res.status !== 200) throw new Error('Health check failed');
  
  const apiRes = await request(app).get('/api/v1/version');
  if (apiRes.status !== 200) throw new Error('API version failed');
  
  return 'PASS';
}
```

### Module Import
```typescript
async function smokeTestImports() {
  const { MainService } = await import('./services/main');
  const service = new MainService();
  if (!service) throw new Error('MainService instantiation failed');
  return 'PASS';
}
```

### Database Connection
```typescript
import { createConnection } from './db';

async function smokeTestDatabase() {
  const conn = await createConnection(':memory:');
  await conn.query('SELECT 1');
  await conn.close();
  return 'PASS';
}
```

### React Component (without DOM)
```typescript
import { renderToString } from 'react-dom/server';
import { App } from './App';

function smokeTestReactApp() {
  const html = renderToString(<App />);
  if (!html.includes('<div')) throw new Error('App render failed');
  return 'PASS';
}
```

### CLI Tool
```typescript
import { execSync } from 'child_process';

function smokeTestCli() {
  const output = execSync('npx my-cli --help', { encoding: 'utf8' });
  if (!output.includes('Usage:')) throw new Error('CLI help failed');
  return 'PASS';
}
```

## Build Check

```bash
# TypeScript compilation
npx tsc --noEmit

# Full build
npm run build

# Check for build output
ls -la dist/ build/ out/ 2>/dev/null

# Monorepo build
npx turbo run build
# or
npx nx run-many --target=build --all
```

Record: build success/failure, total errors, total warnings.

## Package Audit

```bash
# npm
npm audit --json

# pnpm
pnpm audit --json

# yarn
yarn audit --json
```

Report: total vulnerabilities by severity (critical/high/moderate/low).

## UI Verification

### React/Vue Build
```bash
# Should complete without error
npm run build

# Check for type errors in components
npx tsc --project tsconfig.json --noEmit
```

### Next.js
```bash
# Build and export
npx next build

# Check for static issues
npx next lint
```

### Storybook (if present)
```bash
# Build storybook (catches import/render errors)
npx storybook build --quiet
```

## Changed Files Only (CI Mode)

For pull request CI, only check changed files:

```bash
# Get changed TypeScript files
CHANGED=$(git diff --name-only origin/main...HEAD -- '*.ts' '*.tsx')

# Lint only changed files
echo "$CHANGED" | xargs npx eslint

# Type check is always full project (TypeScript needs full context)
npx tsc --noEmit
```