🎯

avoid-unnecessary-type-params

🎯Skill

from marius-townhouse/effective-typescript-skills

VibeIndex|
What it does

Identifies and eliminates unnecessary type parameters in TypeScript to improve type inference and code clarity.

πŸ“¦

Part of

marius-townhouse/effective-typescript-skills(83 items)

avoid-unnecessary-type-params

Installation

Quick InstallInstall with npx
npx skills add marius-townhouse/effective-typescript-skills --all
Quick InstallInstall with npx
npx skills add marius-townhouse/effective-typescript-skills -s prefer-unknown-over-any exhaustiveness-checking
Quick InstallInstall with npx
npx skills add marius-townhouse/effective-typescript-skills -a opencode claude-code
Quick InstallInstall with npx
npx skills add marius-townhouse/effective-typescript-skills -l
git cloneClone repository
git clone https://github.com/marius-townhouse/effective-typescript-skills.git
πŸ“– Extracted from docs: marius-townhouse/effective-typescript-skills
1Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Use when writing generic functions or types. Use when reviewing type signatures. Use when a type parameter only appears once. Use when tempted to add generics for "flexibility".

Overview

# Avoid Unnecessary Type Parameters

Overview

The "Golden Rule of Generics" states that type parameters should appear twice or more in a function signature. If a type parameter only appears once, it's not relating anything and is likely unnecessary. Unnecessary type parameters create a false sense of type safety and can make inference less successful.

This skill helps you identify and eliminate superfluous type parameters, resulting in cleaner, more maintainable code that TypeScript can infer more effectively.

When to Use This Skill

  • Writing generic functions or types
  • Reviewing type signatures for clarity
  • A type parameter appears only once (besides its declaration)
  • Tempted to add generics for "flexibility"
  • Debugging poor type inference

The Iron Rule

Type parameters must appear twice or more to establish a relationship. If a type parameter only appears once, strongly reconsider if you need it.

Detection

Watch for these patterns:

```typescript

// RED FLAGS - Unnecessary type parameters

function parseYAML(input: string): T; // Return-only generic

type Fn = (x: T) => void; // T only used once

function third(a: A, b: B, c: C): C; // A and B appear once

function getLength(x: T): number; // T only in parameter

```

The Golden Rule

Type parameters are for relating types. If a type parameter only appears once, it's not relating anything:

```typescript

// GOOD: T appears twice, relating input and output

function identity(arg: T): T {

return arg;

}

// BAD: T only appears once (in return type)

function parseYAML(input: string): T;

// Equivalent to: function parseYAML(input: string): any

// Usage shows the problem:

const data: User = parseYAML('...'); // Looks safe, but T can be anything

const bad: Banana = parseYAML('...'); // Also "valid" - no error!

```

Return-Only Generics

Return-only generics are dangerous because they're equivalent to type assertions without the explicit as:

```typescript

// BAD: Return-only generic

declare function parseYAML(input: string): T;

const user: User = parseYAML('...'); // No error, but no validation either

// GOOD: Return unknown, force explicit assertion

declare function parseYAML(input: string): unknown;

const user = parseYAML('...') as User; // Explicit about the assertion

// Or use validation:

const user = parseYAML('...');

if (isUser(user)) { // Type guard

// user is User here

}

```

Simplifying Unnecessary Generics

```typescript

// BEFORE: Unnecessary type parameters

function third(a: A, b: B, c: C): C {

return c;

}

// AFTER: Only keep C which appears twice

function third(a: unknown, b: unknown, c: C): C {

return c;

}

```

When Generics ARE Needed

```typescript

// GOOD: K appears twice, relating parameter to return type

function getProperty(obj: T, key: K): T[K] {

return obj[key];

}

// K appears in: parameter type (key: K) and return type (T[K])

// This IS a good use of generics

```

Class Generics

```typescript

// GOOD: T appears multiple times, relating class properties

class Container {

private items: T[] = [];

add(item: T): void { this.items.push(item); }

getAll(): T[] { return this.items; }

}

// BAD: T only used in one method

class Joiner {

join(els: T[]): string {

return els.map(String).join(',');

}

}

// Better: Move T to method or use concrete type

class Joiner {

join(els: (string | number)[]): string {

return els.map(String).join(',');

}

}

// Best: Just a function

function join(els: (string | number)[]): string {

return els.map(String).join(',');

}

```

Pressure Resistance Protocol

When pressured to add "flexible" generics:

  1. Count appearances: Does the type parameter appear twice or more?
  2. Check relationships: Is it relating multiple values' types?
  3. Consider unknown: Would unknown work just as well?
  4. Test inference: Does the generic improve or hurt type inference?

Red Flags

| Anti-Pattern | Why It's Bad |

|--------------|--------------|

| function f(): T | Return-only, no type safety |

| type Fn = (x: T) => void | T not used in return, unnecessary |

| Generics for single-use types | Adds complexity without benefit |

| T extends X where T only appears once | Constraint doesn't help |

Common Rationalizations

"It makes the API more flexible"

Reality: Unnecessary generics create a false sense of safety. They don't add real flexibility, just confusion.

"I'll need it later"

Reality: Add generics when you need them, not in anticipation. You can always add them later.

"It looks more professional"

Reality: Simple, correct types are more professional than complex, unnecessary ones.

Quick Reference

| Pattern | Verdict | Fix |

|---------|---------|-----|

| function f(x: T): T | βœ“ Good | T relates input to output |

| function f(x: string): T | βœ— Bad | Use unknown or concrete type |

| function f(x: T): void | βœ— Bad | Use unknown or any |

| class C { method(x: T): T } | βœ“ Good | T relates multiple uses |

| class C { method(x: T): void } | βœ— Bad | Move T to method or remove |

The Bottom Line

The first rule of generics is "don't." Only add type parameters when they establish relationships between types. If a type parameter appears only once, eliminate it. This results in cleaner code and better type inference.

Reference

  • Effective TypeScript, 2nd Edition by Dan Vanderkam
  • Item 51: Avoid Unnecessary Type Parameters

More from this repository10

🎯
tsdoc-comments🎯Skill

Generates TypeScript documentation comments (TSDoc) to explain public APIs, complex types, and provide comprehensive code documentation with IDE tooltips.

🎯
async-over-callbacks🎯Skill

Transforms callback-based asynchronous code into clean, readable async/await patterns for better type flow and error handling.

🎯
type-safe-monkey-patching🎯Skill

Enables type-safe runtime extension of global objects and DOM elements in TypeScript without sacrificing type checking or using `as any`.

🎯
create-objects-all-at-once🎯Skill

Efficiently initializes multiple TypeScript objects simultaneously using concise object literal syntax and spread operators.

🎯
module-by-module-migration🎯Skill

Guides developers through systematic TypeScript module migration, breaking down complex refactoring into manageable, incremental steps.

🎯
ts-js-relationship🎯Skill

Explains TypeScript's relationship to JavaScript, highlighting how it adds static typing and catches errors before runtime while remaining fully compatible with JavaScript code.

🎯
code-gen-independent🎯Skill

Generates JavaScript code despite TypeScript type errors and demonstrates that TypeScript types are erased at runtime, requiring alternative type checking strategies.

🎯
context-type-inference🎯Skill

Helps restore precise type context when extracting values, preventing type inference errors through annotations, const assertions, and type preservation techniques.

🎯
precise-string-types🎯Skill

Enforces strict string type constraints and prevents unintended string type conversions in TypeScript projects.

🎯
type-display-attention🎯Skill

Displays and simplifies complex TypeScript types to improve IDE readability and developer experience.