Use when writing code in typed languages - enforces full typing with no any/unknown/untyped escapes, even if it requires extra time
Enforces complete type safety across typed languages, eliminating any/unknown escapes.
/plugin marketplace add troykelly/claude-skills/plugin install issue-driven-development@troykelly-skillsThis skill cannot use any tools. It operates in read-only mode without the ability to modify files or execute commands.
No any types. No unknown escapes. Everything fully typed.
Core principle: Types are documentation that the compiler verifies.
This skill applies to: TypeScript, Python (with type hints), Go, Rust, Java, C#, and any typed language.
NEVER use any, unknown, or equivalent type escapes.
ALWAYS provide explicit, accurate types.
TAKE EXTRA TIME if needed to type correctly.
// NEVER
const data: any = fetchData();
const items: unknown[] = parseItems();
function process(input: any): any { }
const config = {} as any;
// @ts-ignore
// @ts-expect-error (unless truly necessary with documentation)
// ALWAYS
interface UserData {
id: string;
name: string;
email: string;
}
const data: UserData = fetchData();
function process<T extends Processable>(input: T): ProcessResult<T> {
// ...
}
Ensure tsconfig.json has strict mode:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"noUncheckedIndexedAccess": true
}
}
When library types are missing:
// Create type definitions
declare module 'untyped-library' {
export interface Config {
option1: string;
option2: number;
}
export function init(config: Config): void;
}
Or contribute types to DefinitelyTyped.
For API responses or parsed JSON:
// Define expected shape
interface ApiResponse {
users: User[];
pagination: Pagination;
}
// Use type guard for runtime validation
function isApiResponse(data: unknown): data is ApiResponse {
return (
typeof data === 'object' &&
data !== null &&
'users' in data &&
Array.isArray((data as ApiResponse).users)
);
}
// Use with validation
const response = await fetch('/api/users');
const data: unknown = await response.json();
if (!isApiResponse(data)) {
throw new Error('Invalid API response');
}
// data is now typed as ApiResponse
import { z } from 'zod';
const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
});
type User = z.infer<typeof UserSchema>;
// Parse and validate
const user = UserSchema.parse(unknownData);
// user is now typed as User
# NEVER
def process(data): # Missing type hints
pass
def fetch() -> Any: # Using Any
pass
from typing import Any
result: Any = compute()
# ALWAYS
from typing import TypeVar, Generic, Protocol
from dataclasses import dataclass
@dataclass
class User:
id: str
name: str
email: str
def process(data: User) -> ProcessResult:
...
T = TypeVar('T', bound='Processable')
def transform(items: list[T]) -> list[T]:
...
Use strict mypy settings:
# mypy.ini
[mypy]
strict = True
disallow_any_generics = True
disallow_untyped_defs = True
disallow_incomplete_defs = True
check_untyped_defs = True
disallow_untyped_decorators = True
warn_redundant_casts = True
warn_unused_ignores = True
Go is statically typed, but avoid:
// AVOID
interface{} // empty interface
any // Go 1.18+ alias for interface{}
// PREFER
type specific interfaces or concrete types
When interface{} is truly needed, document why and add type assertions.
If typing seems impossible:
Is the type hard to express because the design is complex?
→ Consider simplifying the design
// Instead of any
function process<T>(input: T): T {
return input;
}
// Instead of any for multiple types
type Input = string | number | User;
function process(input: Input): void {
if (typeof input === 'string') {
// input is string
} else if (typeof input === 'number') {
// input is number
} else {
// input is User
}
}
function isUser(value: unknown): value is User {
return (
typeof value === 'object' &&
value !== null &&
'id' in value &&
'name' in value
);
}
If any is truly unavoidable (extremely rare):
// JUSTIFIED: Third-party library `foo` has no types and
// creating accurate types requires reverse-engineering
// the entire library. See issue #123 for type contribution.
// TODO(#456): Remove when @types/foo is available
const result: any = thirdPartyCall();
This should be exceptionally rare.
Proper typing takes time. That's acceptable.
| Situation | Acceptable Time |
|---|---|
| Simple interface | 5 minutes |
| Complex generic | 30 minutes |
| Type guards | 15 minutes |
| Library types | 1 hour |
If typing is taking longer, the design may need reconsideration.
Before committing code:
any typesunknown without type guards@ts-ignore or # type: ignore| Excuse | Response |
|---|---|
| "It's just temporary" | Temporary code becomes permanent. Type it now. |
| "I'll fix types later" | Later never comes. Type it now. |
| "any is faster" | Technical debt is slower. Type it now. |
| "The library has no types" | Create types or use Zod. |
| "It's too complex to type" | Simplify the design. |
This skill is applied by:
issue-driven-development - Step 7This skill ensures:
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.