Fixes TypeScript type safety issues including unsafe member access, assignments, returns, calls, and arguments. Use when encountering @typescript-eslint/no-unsafe-* errors or when working with unknown/any types.
Fixes TypeScript type safety violations from unsafe member access, assignments, returns, calls, and arguments. Use when encountering @typescript-eslint/no-unsafe-* errors or working with unknown/any types.
/plugin marketplace add mgd34msu/goodvibes-plugin/plugin install goodvibes@goodvibes-marketThis skill inherits all available tools. When active, it can use any tool Claude has access to.
scripts/detect-type-issues.jsscripts/generate-type-guard.jsFixes for TypeScript's strict type checking violations. These issues represent real runtime risks where the type system cannot guarantee correctness.
any or unknown type to its sourcenpx tsc --noEmitP1 - Fix this week. Unsafe type operations bypass TypeScript's guarantees and can cause runtime crashes.
Detection: @typescript-eslint/no-unsafe-member-access
Pattern: Accessing properties on any or unknown typed values.
// PROBLEM
function processResponse(data: unknown) {
const name = data.name; // Error: unsafe member access
}
Fix Strategy: Type guard with discriminated union.
// SOLUTION
interface ApiResponse {
name: string;
id: number;
}
function isApiResponse(value: unknown): value is ApiResponse {
return (
typeof value === 'object' &&
value !== null &&
'name' in value &&
'id' in value &&
typeof (value as ApiResponse).name === 'string' &&
typeof (value as ApiResponse).id === 'number'
);
}
function processResponse(data: unknown) {
if (!isApiResponse(data)) {
throw new Error('Invalid API response structure');
}
const name = data.name; // Now type-safe
}
Why: Type guards are reusable, self-documenting, and provide runtime validation. Better than as assertions because they verify shape at runtime.
Detection: @typescript-eslint/no-unsafe-assignment
Pattern: Assigning any typed value to a variable.
// PROBLEM
const config = JSON.parse(fileContents); // any type
Fix Strategy: Parse with validation function.
// SOLUTION
interface Config {
port: number;
host: string;
}
function parseConfig(raw: string): Config {
const parsed: unknown = JSON.parse(raw);
if (
typeof parsed !== 'object' ||
parsed === null ||
typeof (parsed as Config).port !== 'number' ||
typeof (parsed as Config).host !== 'string'
) {
throw new Error('Invalid config structure');
}
return parsed as Config;
}
const config = parseConfig(fileContents); // Properly typed
Why: Explicit validation at parse boundaries catches errors early. Using unknown forces validation before use.
Detection: @typescript-eslint/no-unsafe-return
Pattern: Returning any typed value from a function.
// PROBLEM
function getUser(id: string) {
return database.query(`SELECT * FROM users WHERE id = ?`, [id]);
}
Fix Strategy: Add explicit return type annotation.
// SOLUTION
interface User {
id: string;
name: string;
email: string;
}
async function getUser(id: string): Promise<User | null> {
const result = await database.query<User>(
`SELECT * FROM users WHERE id = ?`,
[id]
);
return result[0] ?? null;
}
Why: Return type annotations serve as documentation and catch type mismatches at function boundaries rather than call sites.
Detection: @typescript-eslint/no-unsafe-call
Pattern: Calling a function with any type.
// PROBLEM
const handler = getHandler(eventType);
handler(event); // unsafe call
Fix Strategy: Type the function reference properly.
// SOLUTION
type EventHandler = (event: Event) => void;
const handlerMap: Record<string, EventHandler> = {
click: handleClick,
submit: handleSubmit,
};
function getHandler(eventType: string): EventHandler | undefined {
return handlerMap[eventType];
}
const handler = getHandler(eventType);
if (handler) {
handler(event); // Now type-safe
}
Why: Function type aliases make callback signatures explicit and reusable.
Detection: @typescript-eslint/no-unsafe-argument
Pattern: Passing any typed value as function argument.
// PROBLEM
const data = JSON.parse(input);
processData(data); // unsafe argument
Fix Strategy: Validate at parse boundary.
// SOLUTION
interface InputData {
items: string[];
count: number;
}
function parseInputData(raw: string): InputData {
const parsed: unknown = JSON.parse(raw);
// validation logic here
return parsed as InputData;
}
const data = parseInputData(input);
processData(data); // Now safe
Why: Fix type at its source rather than at every call site. Centralizes validation.
Detection: Manual search for : any in source files.
Fix Matrix:
| Current Usage | Replacement |
|---|---|
any for unknown data | unknown with type guards |
any for flexible functions | Generic type parameter <T> |
any for complex types | Proper interface definition |
any to silence errors | Fix underlying type issue |
// PROBLEM - any for flexibility
function clone(obj: any): any {
return JSON.parse(JSON.stringify(obj));
}
// SOLUTION - generic
function clone<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj)) as T;
}
// PROBLEM - any for unknown API response
const response: any = await fetch(url);
// SOLUTION - unknown with validation
const response: unknown = await fetch(url).then(r => r.json());
if (!isValidResponse(response)) {
throw new Error('Invalid response');
}
Why: any disables type checking entirely. unknown is the type-safe alternative.
Detection: @typescript-eslint/restrict-template-expressions
Pattern: Using non-string types in template literals.
// PROBLEM
const message = `User: ${user}`; // user might be object
Fix Options:
// Explicit string conversion
const message = `User: ${String(user.name)}`;
// With type guard
const message = `User: ${user?.name ?? 'Unknown'}`;
// JSON for objects
const debugMessage = `Data: ${JSON.stringify(data, null, 2)}`;
Why: Template literals call toString() implicitly, producing [object Object] for objects.
Run the detection script to find all type safety issues in your codebase:
# From skill directory
node scripts/detect-type-issues.js /path/to/src
Output: JSON report of all unsafe operations with file locations and fix suggestions.
Generate a type guard function for a given interface:
node scripts/generate-type-guard.js --interface "User" --file /path/to/types.ts
function isTypeName(value: unknown): value is TypeName {
return (
typeof value === 'object' &&
value !== null &&
'requiredProp' in value &&
typeof (value as TypeName).requiredProp === 'expected-type'
);
}
function isStringArray(value: unknown): value is string[] {
return Array.isArray(value) && value.every(item => typeof item === 'string');
}
type Status = 'pending' | 'active' | 'completed';
function isStatus(value: unknown): value is Status {
return value === 'pending' || value === 'active' || value === 'completed';
}
interface Order {
id: string;
items: OrderItem[];
customer: Customer;
}
function isOrder(value: unknown): value is Order {
if (typeof value !== 'object' || value === null) return false;
const obj = value as Record<string, unknown>;
return (
typeof obj.id === 'string' &&
Array.isArray(obj.items) &&
obj.items.every(isOrderItem) &&
isCustomer(obj.customer)
);
}
For complex validation, consider using Zod:
import { z } from 'zod';
const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
age: z.number().int().positive().optional(),
});
type User = z.infer<typeof UserSchema>;
function parseUser(data: unknown): User {
return UserSchema.parse(data);
}
When to use Zod vs manual type guards:
anyanyany targetsobj[key] can produce anyas unknown as T is usedFix these at the source to prevent propagation through the codebase.
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 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 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.