How to fix Type parameter 'X' is defined but never used in TypeScript
This TypeScript compiler warning occurs when you declare a generic type parameter but don't reference it in the function signature, return type, or implementation. Fix it by using the parameter, removing it, or prefixing with underscore.
Quick fix
Fixes Type parameter 'X' is defined but never used
// Error: Type parameter 'T' is defined but never used
function processData<T>(id: number): void {
console.log(id);
}- Identify where the unused type parameter is declared
- Determine if you actually need the type parameter
- Remove the unused type parameter if unnecessary
- Prefix with underscore for intentionally unused parameters
// Error: Type parameter 'T' is defined but never usedfunction processData<T>(id: number): void {console.log(id);}Type parameter 'X' is defined but never used
What this error means
This error appears when TypeScript's `noUnusedParameters` or `@typescript-eslint/no-unused-vars` rule detects a generic type parameter that's declared but never actually used in your code. Type parameters exist to provide type safety and inference across your function or class, but when they're unused, they serve no purpose and can indicate a mistake or incomplete implementation. For example, declaring `function process<T>(value: string): void {}` triggers this error because `T` is declared but never referenced in the parameter types, return type, or function body. TypeScript flags this as it suggests either the type parameter was forgotten or shouldn't have been declared in the first place. This check helps catch phantom type parameters that were meant to be used but weren't, preventing subtle type safety bugs and keeping your codebase clean. The error became more prominent starting with TypeScript 2.5 when unused parameter detection was enhanced.
Typical symptoms
- Compiler error or ESLint warning showing "Type parameter 'T' is defined but never used"
- Build fails when noUnusedParameters or @typescript-eslint/no-unused-vars is enabled
- Red squiggly lines under generic type parameter declarations in your IDE
- CI/CD pipeline fails due to TypeScript strict checks
Common causes
- Type parameter declared in generic function or class but not used in any parameter types, return type, or implementation
- Leftover type parameter from refactored code that no longer needs generics
- Phantom type parameter intended for compile-time type safety but not referenced anywhere
- Copy-pasted generic function signature without adapting the type parameters to the new context
- Interface merged with class where type parameter is only used in one declaration
How to fix "Type parameter 'X' is defined but never used"
Look at the error message to see which type parameter is flagged as unused. Check your function, class, or interface declaration:
// Error: Type parameter 'T' is defined but never used
function processData<T>(id: number): void {
console.log(id);
}The type parameter T is declared but not referenced in the parameter list, return type, or function body.
Ask yourself: Does this function or class need to be generic? If the type parameter was meant to be used, add it to your signature:
// Fix: Use the type parameter
function processData<T>(data: T): T {
console.log(data);
return data;
}
// Or in the return type
function createArray<T>(): T[] {
return [];
}If you don't need it at all, the next step shows how to remove it.
If the generic isn't needed, simply remove it from the declaration:
// Before
function processData<T>(id: number): void {
console.log(id);
}
// After - no generic needed
function processData(id: number): void {
console.log(id);
}This is the cleanest solution when the type parameter serves no purpose.
For phantom type parameters that you need to keep for type-level reasons (like type branding or constraint enforcement), prefix the name with an underscore:
// Phantom type parameter for type branding
function createBranded<_Brand>(value: string): string & { __brand: _Brand } {
return value as string & { __brand: _Brand };
}
// Or when implementing an interface that requires the generic
interface Handler<T> {
handle(event: unknown): void;
}
// Implementation doesn't use T but must match interface
class MyHandler<_T> implements Handler<_T> {
handle(event: unknown): void {
console.log('handled');
}
}The underscore prefix tells TypeScript and ESLint to ignore this parameter.
If you have many intentionally unused type parameters, configure your ESLint rule to ignore them:
// .eslintrc.json
{
"rules": {
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
]
}
}This allows any parameter or variable starting with underscore to be unused without triggering errors.
For projects where this check is too strict, you can disable it in your TypeScript configuration:
// tsconfig.json
{
"compilerOptions": {
"noUnusedParameters": false,
"noUnusedLocals": false
}
}However, this is not recommended as it reduces type safety. Only use this as a last resort, and prefer using ESLint rules for more granular control.
Advanced notes
Type Parameter Constraints and Defaults
You can add constraints or defaults to make unused type parameters more meaningful:
// With constraint - T still unused but provides compile-time check
function process<T extends string>(id: number): void {
console.log(id);
}
// With default - prevents need to specify type explicitly
function create<T = unknown>(): T[] {
return [];
}Phantom Types for Type Safety
Sometimes unused type parameters serve a purpose at the type level even if not used at runtime. This is called "type branding":
type UserId = string & { __brand: 'UserId' };
type ProductId = string & { __brand: 'ProductId' };
function createUserId<_Brand extends 'UserId'>(id: string): UserId {
return id as UserId;
}The _Brand parameter isn't used in the implementation but ensures type safety at compile time.
Interface and Class Merging
When merging interfaces with classes, type parameters may appear unused in one declaration but used in another:
interface Repository<T> {
find(id: string): T | null;
}
abstract class Repository<_T> {
protected cache: Map<string, unknown> = new Map();
}The underscore prefix on the class prevents the error while maintaining compatibility with the interface.
Frequently asked questions
- What does "Type parameter 'X' is defined but never used" mean?
- This error appears when TypeScript's noUnusedParameters or @typescript-eslint/no-unused-vars rule detects a generic type parameter that's declared but never actually used in your code. Type parameters exist to provide type safety and inference across your function or class, but when they're unused, they serve no purpose and can indicate a mistake or incomplete implementation. For example, declaring function process<T>(value: string): void {} triggers this error because T is declared but never referenced in the parameter types, return type, or function body.
- How do I fix "Type parameter 'X' is defined but never used"?
- This TypeScript compiler warning occurs when you declare a generic type parameter but don't reference it in the function signature, return type, or implementation. Fix it by using the parameter, removing it, or prefixing with underscore.
- What causes "Type parameter 'X' is defined but never used"?
- Type parameter declared in generic function or class but not used in any parameter types, return type, or implementation Leftover type parameter from refactored code that no longer needs generics Phantom type parameter intended for compile-time type safety but not referenced anywhere
- Is the "Type parameter 'X' is defined but never used" error serious?
- It is a low-severity error โ more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- ๐TypeScript Official Documentation
- ๐Typescriptlang.org - generics.html(Official Docs)
- ๐Typescriptlang.org - noUnusedParameters.html(Official Docs)
- ๐
- ๐Github.com - 18370(GitHub)
- ๐Github.com - 2803(GitHub)