Skip to content
Back to skills

Find Type Gaps

ASecurity

Identify functions, methods, and modules missing type annotations in gradually-typed languages (Python, TypeScript, JavaScript), ranked by public visibility and churn.

  • 10 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 6, 2026
developmentjavascripttypescriptpythonrustgojavac#bashnodeexpress

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 6, 2026

npx -y skills add tomzx/agents --skill find-type-gaps --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Find Type Gaps?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Find Type Gaps
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tomzx-find-type-gaps/badge)](https://www.skillsdirectory.com/skills/tomzx-find-type-gaps)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: find-type-gaps
description: Identify functions, methods, and modules missing type annotations in gradually-typed languages (Python, TypeScript, JavaScript), ranked by public visibility and churn.
allowed-tools: Bash, Read, Glob, Grep
argument-hint: "[path]"
---

TODAY=!`date +%Y-%m-%d`

# Find Type Gaps

Identifies missing or incomplete type annotations in gradually-typed codebases. Type coverage is a safety net that supports test coverage: typed code catches a class of bugs at analysis time, makes refactoring safer, and reduces the effort of reading unfamiliar code. This skill lists gaps ranked by how much adding types would help — prioritizing public API surfaces and high-churn files.

## Prerequisites

- Working directory is the root of the repository
- Optional: `$1` — path to limit the scan (defaults to `.`)
- Language support:
  - **Python**: `mypy` (`uv tool install mypy`) or `pyright` (`npm install -g pyright`)
  - **TypeScript**: type errors via `tsc --noEmit`; strict mode gaps via `tsconfig.json` flags
  - **JavaScript**: `@ts-check` JSDoc annotations; `tsc --allowJs --checkJs`
- Not applicable to fully-typed languages (Go, Rust, Java, C#)

## What Counts as a Type Gap

| Language | Gap |
|----------|-----|
| Python | Function parameter with no annotation; return type missing; `Any` used where a concrete type is possible; untyped class attribute |
| TypeScript | `any` used explicitly; `as any` cast; function with implicit `any` parameter; missing return type on exported function |
| JavaScript | No JSDoc `@param`/`@returns`; no `@ts-check` at file top; untyped exported function |

## Steps

### 1. Detect Language

```
find ${1:-.} -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn | head -5
```

Proceed only if Python, TypeScript, or JavaScript files are present. Report "not applicable" for fully-typed languages.

### 2. Measure Type Coverage

**Python — mypy:**
```
mypy ${1:-.} \
  --ignore-missing-imports \
  --no-error-summary \
  --any-exprs-report .mypy-type-report \
  2>/dev/null | rg "error:|note:" | head -40
```

Parse the any-exprs report for per-file coverage:
```
cat .mypy-type-report/any-exprs.txt 2>/dev/null | \
  awk 'NR>1 {print $3"% typed\t"$1}' | sort -n | head -30
```

**Python — pyright (stricter, faster):**
```
pyright ${1:-.} --outputjson 2>/dev/null | \
  python3 -c "
import json, sys
data = json.load(sys.stdin)
for d in data.get('generalDiagnostics', []):
    if 'unknown' in d.get('message','').lower() or 'Any' in d.get('message',''):
        print(d['file'].split('/')[-1], d['range']['start']['line'], d['message'][:80])
" 2>/dev/null | head -30
```

**Python — rg fallback (untyped function signatures):**
```
rg -n "^(    )?def [a-zA-Z_]" -g '*.py' ${1:-.} | \
  rg -v "->.*:" | rg -v "#" | \
  awk -F: '{ if ($0 !~ /: [a-zA-Z\[]/) print }' | head -30
```

Count untyped vs typed:
```
total=$(rg -c "^(    )?def " -g '*.py' ${1:-.} | awk -F: '{s+=$2} END{print s}')
typed=$(rg -c "^(    )?def .*->|^(    )?def .*\) -> " -g '*.py' ${1:-.} | awk -F: '{s+=$2} END{print s}')
echo "Typed functions: $typed / $total"
```

**TypeScript — count explicit `any`:**
```
rg -n ": any\b|as any\b|<any>" \
  -g '*.{ts,tsx}' ${1:-.} | rg -v "node_modules|\.d\.ts|test|spec" | \
  awk -F: '{print $1}' | sort | uniq -c | sort -rn | head -20
```

Check strictness configuration:
```
cat tsconfig.json 2>/dev/null | python3 -c "
import json, sys
cfg = json.load(sys.stdin).get('compilerOptions', {})
flags = ['strict','noImplicitAny','strictNullChecks','strictFunctionTypes','noImplicitReturns']
for f in flags:
    print(f, ':', cfg.get(f, 'not set'))
" 2>/dev/null
```

**JavaScript — check for `@ts-check` adoption:**
```
total_js=$(find ${1:-.} -name "*.js" ! -path "*/node_modules/*" | wc -l)
checked_js=$(rg -l "@ts-check" -g '*.js' ${1:-.} | wc -l)
echo "JS files with @ts-check: $checked_js / $total_js"
```

### 3. Identify High-Value Gaps

Focus on gaps that would provide the most benefit:

**Public API surface** — exported/public functions without types are the highest priority since callers cannot rely on them safely:
```
# Python: public functions (no leading underscore) without return type
rg -n "^def [a-zA-Z]" -g '*.py' ${1:-.} | rg -v " -> " | head -20

# TypeScript: exported functions without return type
rg -n "^export (async )?function [a-zA-Z]" -g '*.ts' ${1:-.} | \
  rg -v "): [a-zA-Z<]" | head -20
```

**`Any` bypasses** — uses of `Any`/`any` that bypass the type system:
```
rg -n "\bAny\b" -g '*.py' ${1:-.} | rg -v "typing_extensions|from typing|import" | head -20
rg -n ": any\b|as any" -g '*.{ts,tsx}' ${1:-.} | \
  rg -v "node_modules|\.d\.ts" | head -20
```

**Untyped class attributes (Python):**
```
rg -n -B1 "self\.[a-zA-Z_]* =" -g '*.py' ${1:-.} | \
  rg -v "__init__|#|annotated|: " | head -20
```

### 4. Cross-Reference with Churn

Untyped code in high-churn files is highest priority — types would catch regressions on every change:
```
git log --since="1 month ago" --name-only --pretty=format: | sort | uniq -c | sort -rn | head -30
```

### 5. Rank Gaps

| Priority | Criteria |
|----------|---------|
| 🔴 High | Public/exported function; appears in high-churn file; `Any` on a core data structure |
| 🟡 Medium | Internal function called from multiple modules; class with untyped attributes |
| 🟢 Low | Private helper; test file; one-off script |

### 6. Suggest Concrete Annotations

For each high-priority gap, read the function and infer the correct type signature from usage:
- Look at call sites to determine what types are actually passed
- Look at return statements to determine return type
- Prefer specific types over `Any`; use `Optional[X]` / `X | None` for nullable values
- Suggest `TypedDict` or `dataclass` where `dict` is used as a structured record

### 7. Check Type Configuration

**Python — verify `mypy` or `pyright` is configured:**
```
cat mypy.ini setup.cfg pyproject.toml 2>/dev/null | rg -A10 "\[mypy\]|\[tool.mypy\]|\[tool.pyright\]"
```

Recommend adding to CI if not present.

**TypeScript — check for strict mode:**
If `strict: true` is not set in `tsconfig.json`, recommend enabling it incrementally:
1. Enable `noImplicitAny` first
2. Then `strictNullChecks`
3. Then full `strict`

### 8. Print the Report

```
# Type Gap Report — {TODAY}

## Summary

- Language(s): <Python / TypeScript / JavaScript>
- Type coverage: X% of functions annotated
- Explicit Any / untyped escapes: N
- 🔴 High-priority gaps: N
- Tools used: <mypy / pyright / tsc / rg>

## Configuration

- mypy / pyright / tsc configured: yes / no
- Strict mode: enabled / partial / not set
- Recommendation: <enable strict mode incrementally / add mypy to CI>

## High-Priority Gaps

### Public API — Untyped Exported Functions (N)

| File | Line | Function | Missing |
|------|------|----------|---------|
| `src/client.py` | 42 | `def fetch(url, timeout)` | param types + return type |

### `Any` Bypasses (N)

| File | Line | Usage | Suggested type |
|------|------|-------|---------------|

### Untyped Core Data Structures (N)

…

## Suggested Annotations

For each high-priority function, a concrete suggested signature:

### `fetch` in `src/client.py:42`

```python
# Before
def fetch(url, timeout=30):

# After
def fetch(url: str, timeout: int = 30) -> dict[str, Any]:
```

## Quick Wins

3–5 annotation additions that would cover the most-used untyped surface area.

## Next Steps

1. Add mypy/pyright to CI with `--strict` (or incremental flags)
2. Address 🔴 gaps in priority order
3. Set a coverage floor and enforce it in CI
```

## Example Usage

**Scenario 1: Python project baseline**
```
/find-type-gaps
```
61% of functions are typed. Public `Client` class has 8 untyped methods — the primary entry point for library users. Generates suggested signatures for all 8 based on call-site analysis.

**Scenario 2: TypeScript strictness audit**
```
/find-type-gaps src/api
```
`strict` mode is off. Finds 34 uses of `as any` and 12 implicit-any function parameters. Recommends enabling `noImplicitAny` first and lists the 12 parameters to fix.

**Scenario 3: Pre-refactor safety check**
```
/find-type-gaps src/payments
```
The payments module is 20% typed. Before refactoring, recommends annotating the 5 core functions so mypy can catch regressions during the refactor.

## Useful Commands Reference

| Command | Description |
|---------|-------------|
| `mypy . --ignore-missing-imports` | Python type check |
| `mypy . --any-exprs-report .report` | Per-file Any expression count |
| `pyright . --outputjson` | Strict Python type check with JSON output |
| `tsc --noEmit` | TypeScript type check without emitting files |
| `rg -n ": any" -g '*.ts'` | Find explicit any in TypeScript |
| `rg -n "^def " -g '*.py' \| rg -v " -> "` | Untyped Python functions |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…