Identify functions, methods, and modules missing type annotations in gradually-typed languages (Python, TypeScript, JavaScript), ranked by public visibility and churn.
Pro shows the line behind each finding and how to fix it
Scanned 10/6/2026
npx -y skills add tomzx/agents --skill find-type-gaps --agent claude-codeInstalls 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 automatically with every re-scan.
[](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.
---
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 |
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!