This error occurs when you attempt to use a generic type in a function without properly declaring its type parameters. TypeScript requires that all generic type parameters be declared in angle brackets before they can be used in function signatures or implementations.
This error appears when TypeScript encounters a generic type being used in a function without the proper type parameter declaration. Generic types are like templates that need to be told what specific type they're working with. When you define a generic function or use a generic type, TypeScript needs to know what placeholder types are available. The error typically occurs in two scenarios: when you try to use a generic type without providing the necessary type arguments, or when you attempt to reference a type parameter in a function implementation that wasn't declared in the function signature. TypeScript's generics system requires explicit declaration of type parameters in angle brackets (like <T>) before those parameters can be referenced anywhere in the function. This is a compile-time error that prevents your code from being transpiled until the generic type parameters are properly declared. It's TypeScript's way of enforcing type safety and ensuring that generic types are used correctly throughout your codebase.
Look at the error message to find the exact location where TypeScript is complaining about undeclared type parameters. The error will point to a specific line and function.
// ❌ Error: Type parameter 'T' is not declared
function processValue(value: T): T {
return value;
}Check if you're using any type parameters (like T, U, K, V) without declaring them first.
Declare the type parameter in angle brackets immediately after the function name and before the parameter list:
// ✅ Correct: Type parameter declared
function processValue<T>(value: T): T {
return value;
}
// Usage
const result = processValue<string>("hello");
const num = processValue(42); // Type inference works tooFor multiple type parameters:
function merge<T, U>(obj1: T, obj2: U): T & U {
return { ...obj1, ...obj2 };
}If you're using a generic interface or type, make sure to provide the required type arguments:
// Generic interface
interface Box<T> {
value: T;
}
// ❌ Error: Generic type 'Box<T>' requires 1 type argument
const myBox: Box = { value: 42 };
// ✅ Correct: Type argument provided
const myBox: Box<number> = { value: 42 };You can also use type inference in many cases:
const myBox = { value: 42 } as Box<number>;When using function overloads with generics, ensure both the overload signatures and implementation signature properly declare type parameters:
// ❌ Error: Implementation missing type parameter
function transform(value: string): string;
function transform(value: number): number;
function transform(value: T): T { // Error!
return value;
}
// ✅ Correct: All signatures properly typed
function transform(value: string): string;
function transform(value: number): number;
function transform<T extends string | number>(value: T): T {
return value;
}If your generic function only works with certain types, add constraints using the extends keyword:
// Only accept types with a length property
function getLength<T extends { length: number }>(item: T): number {
return item.length;
}
getLength("hello"); // ✅ Works
getLength([1, 2, 3]); // ✅ Works
getLength({ length: 5 }); // ✅ Works
// getLength(123); // ❌ Error: number doesn't have lengthFor arrays specifically:
function firstElement<T>(arr: T[]): T | undefined {
return arr[0];
}After adding type parameter declarations, verify that:
1. The TypeScript compiler no longer shows errors
2. Type inference works correctly when calling the function
3. IDE autocomplete provides proper type hints
function identity<T>(value: T): T {
return value;
}
// Test with different types
const str = identity("test"); // Type: string
const num = identity(123); // Type: number
const obj = identity({ id: 1 }); // Type: { id: number }Run tsc --noEmit to check for any remaining type errors.
Generic Type Defaults: You can provide default types for generic parameters to make them optional:
interface Box<T = string> {
value: T;
}
const defaultBox: Box = { value: "hello" }; // Uses default string
const numberBox: Box<number> = { value: 42 };Type Inference Limitations: TypeScript can't always infer generic types perfectly, especially with complex scenarios involving multiple type parameters or constraints. In such cases, you may need to explicitly provide type arguments:
function merge<T, U>(a: T, b: U) { return { ...a, ...b }; }
// Explicit type arguments may be needed in complex cases
const result = merge<{ x: number }, { y: string }>({ x: 1 }, { y: "2" });Arrow Functions and Generics: Arrow functions support generics with the same syntax:
const identity = <T>(value: T): T => value;In TSX/JSX files, you may need to add a comma to avoid ambiguity with JSX syntax:
const identity = <T,>(value: T): T => value;Generic Classes: The same rules apply to generic classes - type parameters must be declared:
class Container<T> {
constructor(private value: T) {}
getValue(): T {
return this.value;
}
}
const container = new Container<string>("hello");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
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript