This TypeScript error occurs when you declare a generic type parameter on a function but never actually use it to relate types in the function parameters or return type. The type parameter serves no purpose and should either be removed or properly utilized.
This error appears when TypeScript detects a generic type parameter that doesn't actually relate types in your function signature. Generic type parameters exist to create relationships between the types of multiple values - typically between parameters and return values, or between different parameters. When a type parameter appears only once (or not at all) in a function signature, it's not serving its purpose. TypeScript flags this because it makes the function unnecessarily complex and can mislead developers into thinking type safety exists where it doesn't. The compiler or ESLint (with @typescript-eslint/no-unnecessary-type-parameters rule) will warn you about this pattern. A type parameter that isn't used in the signature essentially forces callers to manually specify an extra type argument for no benefit, making the code harder to read and reason about without providing any actual type safety.
Examine your function signature to see if the type parameter appears in:
- Parameter types
- Return type
- Type constraints
Example of unused type parameter:
function example<T>(): void {
// T is declared but never used in signature
}The type parameter T is declared but doesn't appear in the function parameters or return type, making it useless.
If the type parameter doesn't relate types in your function, simply remove it:
Before:
function doSomething<T>(message: string): void {
console.log(message);
}After:
function doSomething(message: string): void {
console.log(message);
}This is the cleanest solution when the generic provides no value.
If you need the generic behavior, ensure the type parameter relates at least two values:
Before (incorrect):
function identity<T>(): string {
return "something";
}After (correct):
function identity<T>(value: T): T {
return value;
}Now T relates the input type to the output type, providing real type safety.
If you're using the generic just to force a specific type, use explicit types instead:
Before (bad pattern):
function getData<T>(): T {
return JSON.parse(data) as T;
}
const user = getData<User>();After (better):
function getData(): unknown {
return JSON.parse(data);
}
const user = getData() as User;Or even better, use proper type guards or validation.
If you need to constrain what can be passed to a function, ensure the type parameter is used:
Correct usage:
function processArray<T extends string | number>(items: T[]): T[] {
return items.filter(item => item !== null);
}Here T is used in both the parameter type and return type, creating a proper relationship.
Add the @typescript-eslint/no-unnecessary-type-parameters rule to your ESLint configuration:
{
"rules": {
"@typescript-eslint/no-unnecessary-type-parameters": "error"
}
}This will automatically flag unused type parameters during development, helping you maintain cleaner code.
Type Parameters vs Type Arguments
Type parameters are for *relating* types, not just *specifying* types. The TypeScript documentation recommends: "Always use as few type parameters as possible." If a type parameter only appears once in your signature, ask yourself if it's actually creating a relationship or just adding noise.
Implementation vs Signature
The rule only counts usages in the *signature* (parameters and return type), not in the *implementation* (function body). Using a type only inside the function body doesn't count as "using" it for type safety purposes.
Valid Single-Use Cases
There are rare exceptions where a type parameter appears only once but is still valuable:
- When used in type constraints for overload resolution
- When used with declaration merging patterns
- When providing a type hint for IDE inference
In these cases, you can disable the ESLint rule with // eslint-disable-next-line and add a comment explaining why.
Generic Classes and Methods
This pattern applies to class methods and constructors too. A generic method that doesn't use its type parameter in the method signature should either use it properly or be made non-generic.
Type parameter 'X' is defined but never used
How to fix "Type parameter is defined but never used" in TypeScript
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript