type-strictness
Enforce strict type compliance by eliminating `Any` types and `# type: ignore` comments. Use when: (1) Editing code that contains `Any` as a type annotation (2) Code has `# type: ignore` or `# pyright: ignore` comments (3) User requests type fixes or type strictness enforcement (4) Importing from untyped third-party libraries (5) User asks to "fix types", "remove Any", or "add proper typing" (6) Pyrefly or mypy reports type errors that need resolution (7) Code review reveals weak typing patterns Follows hierarchical resolution: codebase inference → type stubs → library inspection → type guards → casting (last resort).
- License 许可
- MIT
- 最近更新
- 2026-11-12
- Stars
- ★ 1
- Forks
- 0
01 前言 Front Matter
- name
- type-strictness
- description
- Enforce strict type compliance by eliminating `Any` types and `# type: ignore` comments. Use when: (1) Editing code that contains `Any` as a type annotation (2) Code has `# type: ignore` or `# pyright: ignore` comments (3) User requests type fixes or type strictness enforcement (4) Importing from untyped third-party libraries (5) User asks to "fix types", "remove Any", or "add proper typing" (6) Pyrefly or mypy reports type errors that need resolution (7) Code review reveals weak typing patterns Follows hierarchical resolution: codebase inference → type stubs → library inspection → type guards → casting (last resort).
02 资源文件 4
- 参考文档references/common-stubs.md3.4 KB
- 参考文档references/error-code-fixes.md7.8 KB
- 参考文档references/resolution-patterns.md11.9 KB
- 参考文档references/third-party-typing.md12.2 KB
03 SKILL.md 正文
Type Strictness
Eliminate Any types and type suppression comments through systematic resolution.
Core Principle
Never suppress type errors. Always fix them.
The type system exists to catch bugs. Suppressing errors with Any, # type: ignore, or linter config changes defeats this purpose and hides real issues that will manifest as runtime bugs.
Resolution Hierarchy
┌─────────────────────────────────────────────────────────────────┐
│ 1. INFER FROM CODEBASE │
│ Search for existing type definitions, protocols, base │
│ classes. Use find_symbol, find_referencing_symbols. │
├─────────────────────────────────────────────────────────────────┤
│ 2. FIND TYPE STUBS │
│ Search PyPI for types-{package} or {package}-stubs. │
│ Check typeshed for stdlib/popular package coverage. │
├─────────────────────────────────────────────────────────────────┤
│ 3. INSPECT LIBRARY SOURCE │
│ Read library source for method signatures, return types. │
│ Use site-packages inspection or GitHub source. │
├─────────────────────────────────────────────────────────────────┤
│ 4. TYPE GUARDS & NARROWING │
│ Use TypeGuard, isinstance, hasattr checks. │
│ See references/resolution-patterns.md │
├─────────────────────────────────────────────────────────────────┤
│ 5. CASTING (LAST RESORT) │
│ Only when all above fail and type is provably correct. │
│ Document why cast is necessary. │
└─────────────────────────────────────────────────────────────────┘
Forbidden Patterns
| Pattern | Why Forbidden | Action |
|---|---|---|
Any |
Disables type checking | Resolve through hierarchy |
# type: ignore |
Hides real issues | Fix underlying error |
# type: ignore[code] |
Still suppresses | Fix the specific issue |
# pyright: ignore |
Same as above | Fix underlying error |
# noqa (for type errors) |
Circumvents linting | Address the actual issue |
object as catch-all |
Poor typing | Use Protocol or Union |
| Modifying strictness config | Weakens entire codebase | Fix issues individually |
cast(Any, x) |
Undermines type system | Use specific cast type |
-> None # type: ignore |
Lying about return | Fix return annotation |
Also Forbidden
- Changing
strict = truetofalsein pyproject.toml - Disabling specific pyright rules in config
- Adding packages to mypy's
ignore_missing_imports - Using
--no-strict-optionalor similar flags
Phase 1: Detect Issues
Run type checker to identify issues:
# Pyrefly (preferred)
pyrefly check src/ --output-format json 2>/dev/null | python3 -c "
import sys, json
d = json.load(sys.stdin)
for e in d.get('errors', []):
print(f\"{e['path']}:{e['line']}:{e['column']} [{e['severity']}] {e['name']} - {e['concise_description']}\")
"
# Mypy alternative
mypy src/ --show-error-codes 2>&1 | grep -E "(Any|type: ignore)"
Search for violations:
# Find Any types
grep -rn ":\s*Any" --include="*.py" src/
grep -rn "-> Any" --include="*.py" src/
grep -rn "list\[Any\]" --include="*.py" src/
# Find type ignores
grep -rn "# type: ignore" --include="*.py" src/
grep -rn "# pyright: ignore" --include="*.py" src/
Phase 2: Resolve Types
Step 1: Codebase Inference
Search for existing definitions:
# Find where the type is actually defined
find_symbol(name_path_pattern="ClassName", include_body=True)
# Find how it's used elsewhere (reveals expected type)
find_referencing_symbols(name_path="function_name", relative_path="module.py")
# Search for protocol definitions
search_for_pattern(
substring_pattern="class.*Protocol",
paths_include_glob="**/domain/**/*.py"
)
Step 2: Find Type Stubs
Common stub packages:
| Library | Stub Package |
|---|---|
| requests | types-requests |
| redis | types-redis |
| PyYAML | types-PyYAML |
| python-dateutil | types-python-dateutil |
| Pillow | types-Pillow |
| boto3 | boto3-stubs |
| SQLAlchemy | Built-in (2.0+) |
Check availability:
# Search PyPI for stubs
pip index versions types-{package} 2>/dev/null
pip index versions {package}-stubs 2>/dev/null
For complete list: See references/common-stubs.md
Step 3: Library Inspection
Inspect installed package:
# Find package location
python3 -c "import {package}; print({package}.__file__)"
# Read source for signatures
python3 -c "import {package}; help({package}.{function})"
Step 4: Type Guards & Narrowing
See references/resolution-patterns.md for:
- TypeGuard functions
- isinstance narrowing
- hasattr checks
- Protocol definitions
- Overload patterns
Step 5: Casting (Last Resort)
Only if:
- All resolution steps exhausted
- Type is provably correct at runtime
- Documented with justification
from typing import cast
# BAD: unexplained cast
value = cast(str, unknown_value)
# ACCEPTABLE: documented necessity
# cast required: third-party lib returns untyped dict but structure is documented
config = cast(dict[str, int], load_config())
Tool Usage
| Tool | Purpose |
|---|---|
pyrefly check / mypy |
Identify type errors |
find_symbol |
Find existing type definitions |
find_referencing_symbols |
Infer types from usage |
search_for_pattern |
Find Protocol/TypeVar patterns |
pip index versions |
Check for type stubs |
python -c "help(...)" |
Inspect library signatures |
Output Checklist
After fixing, verify:
- [ ] No
Anytypes remain (except in unavoidable edge cases with documentation) - [ ] No
# type: ignorecomments - [ ] No
# pyright: ignorecomments - [ ] No linter config modifications that weaken type checking
- [ ] Type checker passes:
pyrefly check src/ - [ ] If cast used, justification comment present
- [ ] Stubs installed for all third-party imports
Reference Documents
| Reference | Contents |
|---|---|
references/error-code-fixes.md |
Pyrefly/Mypy error codes with specific fix strategies |
references/resolution-patterns.md |
Advanced typing patterns: TypeGuard, Protocol, TypeVarTuple, Self, etc. |
references/common-stubs.md |
Type stub packages for popular libraries |
references/third-party-typing.md |
Strategies for typing untyped library code |
Quick Decision Tree
Got a type error?
│
├─ Is it "Unknown type" or missing annotation?
│ └─ Add explicit type annotation at source
│
├─ Is it from third-party library?
│ ├─ Check for types-{pkg} stubs → Install
│ ├─ Check for {pkg}-stubs → Install
│ ├─ Library has py.typed? → Already typed, check version
│ └─ No stubs? → Create local .pyi stub (see third-party-typing.md)
│
├─ Is it a return type mismatch?
│ ├─ Function can return None? → Add `| None` to return type
│ ├─ Missing return path? → Add the return statement
│ └─ Wrong type returned? → Fix the return value
│
├─ Is it an argument type mismatch?
│ ├─ Can widen parameter? → Use Union or Protocol
│ ├─ Call site wrong? → Fix the call site
│ └─ Need overloads? → Add @overload signatures
│
├─ Is it Optional/None access?
│ ├─ Add None check before access
│ ├─ Use early return pattern
│ └─ Use walrus operator for assignment+check
│
└─ Complex dynamic type?
├─ Create TypedDict for dict structures
├─ Create Protocol for duck typing
├─ Use TypeGuard for runtime checks
└─ See resolution-patterns.md for advanced patterns
Common Scenarios
JSON Data
# BAD
def parse(data: str) -> dict[str, Any]:
return json.loads(data)
# GOOD
class UserData(TypedDict):
id: int
name: str
def parse(data: str) -> UserData:
result = json.loads(data)
# Validate structure
if not is_user_data(result):
raise ValueError("Invalid data")
return result
Callback Functions
# BAD
def register(callback: Callable[..., Any]) -> None: ...
# GOOD
from typing import ParamSpec, TypeVar
P = ParamSpec("P")
R = TypeVar("R")
def register(callback: Callable[P, R]) -> Callable[P, R]: ...
Dictionary Access
# BAD
config: dict[str, Any] = load_config()
timeout = config["timeout"] # Unknown type
# GOOD
class Config(TypedDict):
timeout: int
retries: int
config: Config = load_config()
timeout = config["timeout"] # int
Optional Chaining
# BAD (suppresses error)
user: User | None = get_user()
name = user.name # type: ignore
# GOOD
user: User | None = get_user()
if user is not None:
name = user.name
# OR
name = user.name if user else "Unknown"
Modern Python Features (3.10+)
Prefer modern syntax for cleaner types:
| Old Style | Modern Style |
|---|---|
Optional[str] |
str | None |
Union[int, str] |
int | str |
List[str] |
list[str] |
Dict[str, int] |
dict[str, int] |
Tuple[int, ...] |
tuple[int, ...] |
Type[T] |
type[T] |
When You're Truly Stuck
If after exhausting all options a type truly cannot be resolved:
- Isolate it: Create a wrapper function/module that contains the untyped code
- Document it: Add a detailed comment explaining why typing isn't possible
- Minimize scope: Use the most specific type possible, not
Any - Open an issue: If it's a library bug, report it upstream
Example of acceptable containment:
# _untyped_wrappers.py
"""Wrappers for genuinely untyped library code.
Each wrapper isolates untyped library calls and provides typed interfaces.
Document why each is necessary.
"""
def get_legacy_config() -> dict[str, str]:
"""Wrap legacy_lib.config() which has no types and no stubs.
Library is unmaintained (last update 2019) and we're migrating away.
The return type is validated at runtime.
"""
from legacy_lib import config # Untyped import contained here
result = config()
if not isinstance(result, dict):
raise TypeError("Unexpected config type")
return {str(k): str(v) for k, v in result.items()}
04 同仓库更多 Skills
slopgate-test-extender
Extend Python test suites with parametrization, fixture reuse, and quality enforcement. Use when asked to add tests, extend existing tests, improve test coverage, consolidate duplicate tests, fix test quality issues, or when Slopgate reports untested-production-code, missing test references, or coverage gaps. Triggers on requests like "add tests for X", "extend these tests", "parametrize tests", "consolidate tests", "fix test quality", "improve test coverage", "write tests for this function", "test this module", "behavior tests", "integration tests", "missing tests", "coverage holes", "untested code", or when a hook denies with test-related findings.
slopgate-intelligent-coding-patterns
Pattern-selection playbook for agents editing code with complex branching, stateful parsers/workflows, duplicated skeletons, policy checks, or ordered transforms. Load before refactoring if/elif dispatch chains, boolean-flag state machines, repeated validation predicates, parallel provider/language implementations, or regex/content transformation pipelines. Also load when asked to "apply a design pattern", "which pattern should I use here", "refactor this switch statement", "replace if-elif chain", "state machine pattern", "strategy pattern", "template method", "pipeline pattern", "specification pattern", "dispatch table", "guard clause refactor", "reduce cyclomatic complexity", or when Slopgate fires PY-CODE-014, PY-CODE-017, PY-CODE-018, QUALITY-LINT-001, or PY-QUALITY-010. Use with behavior-locking tests and avoid pattern theater for simple one-off code.
slopgate-hygiene-orchestrator
Orchestrate systematic elimination of linter warnings and errors across Python, TypeScript, and Rust codebases. Use when asked to "clean up lints", "fix all warnings", "run hygiene", "eliminate type errors", "orchestrate code quality fixes", "fix lint errors", "resolve quality gate failures", "pass CI checks", "reduce tech debt", "refactor to pass hooks", or when a Slopgate hook denies with QUALITY-LINT-001, PY-CODE-017, PY-CODE-018, or any collector finding. This skill coordinates multiple code-hygiene-enforcer agents working in parallel on non-conflicting file groupings, tracks progress persistently via JSON exports, and loops until all issues are resolved. CRITICAL: Never run linters directly—always use `slopgate lint check` as the primary gate, discover project-specific tools from config files, and export findings to JSON for tracking.
slopgate-code-smell-utility-locator
Autoactivate when code-smell hooks or reviews mention feature envy, thin wrappers, duplicate helpers, duplicate code, scattered helpers, builders/factories/config/constants/dataclass reuse, PY-CODE-012, PY-CODE-013, QUALITY-LINT-001, or repeated slopgate code-quality denials. Also load when asked to "find existing helpers", "consolidate utilities", "search for duplicate code", "where is this already implemented", "reuse existing logic", "don't duplicate this", "find similar functions", "utility inventory", "code smell radar", or before adding new helpers/wrappers so agents can find existing shared utilities and consolidate instead of duplicating.
slopgate-code-hygiene-refactor
Recovery playbook for Slopgate and project quality failures. Load after hook/lint denials such as PY-CODE-017 flat sibling modules, PY-CODE-018 oversized modules, QUALITY-LINT-001 post-edit quality backstops, PY-QUALITY-010 magic numbers / repeated literals, PY-CODE-012/PY-CODE-013 smell findings, type-suppression bans, duplicate helpers, or repeated hygiene retry loops. Also load when asked to "refactor this module", "split this file", "extract a class", "reduce complexity", "fix god class", "flatten module hierarchy", "move code to a package", "extract helpers", "consolidate duplicates", "replace magic numbers with constants", or when a hook blocks an edit with structural complaints. Focuses on preserving public APIs while refactoring toward packages, cohesive modules, typed seams, and focused tests.
rtk-cli
Use when running shell commands in agent sessions to cut Bash output tokens, or when the user asks to install/configure RTK, reduce context from git/test/lint commands, or use rtk git/rg/cargo wrappers. Triggers on "rtk", "token savings", "compact git status", or heavy command output eating context.