This TypeScript error occurs when you use a generic type without providing the required type arguments. Generic types in TypeScript need explicit type parameters to define what types they operate on. The fix involves adding the missing type arguments or using type inference where possible.
The "Generic type requires type argument(s)" error (TS2314) appears when you reference a generic type without providing the necessary type parameters. Generic types are templates that can work with multiple types, but they need to know which specific type(s) to use for each instance. In TypeScript, generic types are declared with type parameters in angle brackets (e.g., `Array<T>`, `Promise<T>`, `Map<K, V>`). When you use these types, you must either: 1. Provide explicit type arguments: `Array<string>` 2. Let TypeScript infer them from context: `const arr = [] // inferred as any[]` 3. Use default type parameters if available: `Array<any>` The error typically occurs when: - Using built-in generic types like `Array`, `Promise`, `Map`, `Set` without type arguments - Using custom generic classes/interfaces without specifying type parameters - Importing generic types from libraries and forgetting to add type arguments - Type inference fails in complex scenarios
For built-in TypeScript generic types, provide the type parameter in angle brackets:
// WRONG - missing type argument
const numbers: Array = [1, 2, 3]; // Error: Generic type 'Array<T>' requires 1 type argument(s)
// CORRECT - add type argument
const numbers: Array<number> = [1, 2, 3];
// Other common built-in generics:
const promise: Promise<string> = Promise.resolve("hello");
const map: Map<string, number> = new Map();
const set: Set<boolean> = new Set();
const record: Record<string, number> = { count: 42 };
// For React components with props:
const Component: React.FC<Props> = ({ title }) => <div>{title}</div>;If you don't know the exact type, you can use:
- any: Array<any> (least type-safe)
- unknown: Array<unknown> (type-safe but requires type checking)
- Union types: Array<string | number>
- The specific type your data uses
When using your own generic types, provide the required type arguments:
// Generic interface definition
interface Response<T> {
data: T;
status: number;
}
// WRONG - missing type argument
const response: Response = { data: "hello", status: 200 }; // Error
// CORRECT - specify type argument
const response: Response<string> = { data: "hello", status: 200 };
// Generic class example
class Container<T> {
constructor(public value: T) {}
}
// WRONG
const container: Container = new Container("test"); // Error
// CORRECT
const container: Container<string> = new Container("test");
// Multiple type parameters
interface Pair<K, V> {
key: K;
value: V;
}
// WRONG - needs 2 type arguments
const pair: Pair = { key: "id", value: 123 }; // Error
// CORRECT
const pair: Pair<string, number> = { key: "id", value: 123 };Check the generic type definition to see how many type parameters it expects.
TypeScript can often infer generic types from context, avoiding the need for explicit type arguments:
// Let TypeScript infer the type
const numbers = [1, 2, 3]; // Inferred as number[]
const promise = Promise.resolve("hello"); // Inferred as Promise<string>
// For functions, inference works on parameters and return types
function identity<T>(value: T): T {
return value;
}
// TypeScript infers T as string
const result = identity("test"); // result is string
// With arrays, provide initial values for inference
// WRONG - empty array, can't infer type
const items = []; // Inferred as any[], but better to specify
// CORRECT options:
const items: string[] = []; // Explicit type
const items = [] as string[]; // Type assertion
const items: Array<string> = []; // Generic syntax
// For React useState with generics:
const [count, setCount] = useState<number>(0); // Explicit
const [count, setCount] = useState(0); // Inferred as numberType inference works best when there's enough context for TypeScript to determine the types.
When using generic types from external libraries, ensure you provide type arguments:
// Example with axios
import axios from 'axios';
// WRONG - missing type argument for AxiosResponse
const response: AxiosResponse = await axios.get('/api/data');
// CORRECT - specify the data type
const response: AxiosResponse<User> = await axios.get('/api/data');
// Example with Redux Toolkit
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface CounterState {
value: number;
}
// WRONG - missing type argument for createSlice
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => { state.value += 1; },
},
});
// CORRECT - specify state type
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 } as CounterState,
reducers: {
increment: (state) => { state.value += 1; },
},
});
// For PayloadAction generic:
reducers: {
incrementBy: (state, action: PayloadAction<number>) => {
state.value += action.payload;
},
}Check the library's documentation or type definitions to see what type parameters are required.
Some generic types have constraints or default type parameters:
// Generic with constraint
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
// Must satisfy the constraint
loggingIdentity({ length: 10, value: 3 }); // OK
loggingIdentity(3); // Error: number doesn't have .length
// Generic with default type parameter
interface Container<T = string> {
value: T;
}
// Can use default
const container1: Container = { value: "hello" }; // T defaults to string
// Or override it
const container2: Container<number> = { value: 42 };
// React example with default props
interface Props {
title: string;
count?: number;
}
const Component: React.FC<Props> = ({ title, count = 0 }) => (
<div>{title}: {count}</div>
);
// Using Partial<T> utility type
const update: Partial<Props> = { title: "New Title" };Check if the generic type has default parameters that you can rely on.
For more complex cases, you might need additional techniques:
// 1. Use type parameters in function declarations
function firstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
// 2. Generic type aliases
type Nullable<T> = T | null;
const value: Nullable<string> = "hello";
// 3. Mapped types
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
// 4. Conditional types
type IsString<T> = T extends string ? true : false;
// 5. Fixing React component generics
interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
function List<T>({ items, renderItem }: ListProps<T>) {
return <div>{items.map(renderItem)}</div>;
}
// Usage - TypeScript infers T from items
<List items={[1, 2, 3]} renderItem={(num) => <span>{num}</span>} />
// 6. Using keyof and indexed access
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const person = { name: "Alice", age: 30 };
const name = getProperty(person, "name"); // string
const age = getProperty(person, "age"); // numberWhen dealing with complex generics, break down the problem and add type annotations step by step.
### Understanding Generic Type Parameters
Generic types in TypeScript are parameterized types that can work with multiple data types while maintaining type safety. The syntax Type<T> means "Type parameterized by T".
Common built-in generic types:
- Array<T>: Array containing elements of type T
- Promise<T>: Promise that resolves to type T
- Map<K, V>: Map with keys of type K and values of type V
- Set<T>: Set containing elements of type T
- Record<K, T>: Object with keys of type K and values of type T
- Partial<T>: Makes all properties of T optional
- Readonly<T>: Makes all properties of T readonly
### Type Argument Inference Rules
TypeScript infers type arguments in these scenarios:
1. Function calls: identity("hello") infers T as string
2. Array literals: [1, 2, 3] infers T as number
3. Object literals: { x: 10, y: 20 } infers shape
4. Contextual typing: In callbacks and event handlers
When inference fails:
- Empty arrays: [] defaults to any[] (use as Type[] or explicit type)
- Uninitialized variables: let x; is any (add type annotation)
- Ambiguous contexts: Multiple possible types (use explicit type arguments)
### Generic Constraints and Defaults
Constraints (T extends Constraint):
interface HasId {
id: string;
}
function processItem<T extends HasId>(item: T): void {
console.log(item.id);
}Default type parameters:
interface ApiResponse<T = any> {
data: T;
status: number;
}
// Uses default any
const response1: ApiResponse = { data: "test", status: 200 };
// Overrides default
const response2: ApiResponse<User> = { data: user, status: 200 };### Utility Types for Common Patterns
TypeScript provides utility types that are themselves generic:
- Partial<T>: Make all properties optional
- Required<T>: Make all properties required
- Readonly<T>: Make all properties readonly
- Pick<T, K>: Pick subset of properties
- Omit<T, K>: Omit properties
- ReturnType<T>: Get function return type
- Parameters<T>: Get function parameters as tuple
### React and Generic Components
React components often use generics for props:
interface TableProps<T> {
data: T[];
columns: Column<T>[];
keyExtractor: (item: T) => string;
}
function Table<T>({ data, columns, keyExtractor }: TableProps<T>) {
return (
<table>
{data.map(item => (
<tr key={keyExtractor(item)}>
{columns.map(col => (
<td>{col.render(item)}</td>
))}
</tr>
))}
</table>
);
}
// Usage with type inference
<Table
data={users}
columns={userColumns}
keyExtractor={user => user.id}
/>### Debugging Generic Type Errors
Use these techniques to debug generic type issues:
1. Check type definitions: cmd+click (Mac) or ctrl+click (Windows) on the type in VS Code
2. Use type assertions temporarily: const x = value as any; to bypass errors while debugging
3. Add explicit type parameters: Start with any, then refine to more specific types
4. Use TypeScript Playground: Test generic types in isolation at [TypeScript Playground](https://www.typescriptlang.org/play)
### Common Pitfalls
1. Forgetting type arguments on React hooks: useState<number>(0) vs useState(0)
2. Empty arrays without type annotations: [] becomes any[]
3. Missing type arguments on library imports: Check library documentation
4. Generic constraints too restrictive: Loosen constraints with union types
5. Inference failures in callbacks: Add explicit type annotations to callback parameters
Remember: Generic types provide type safety at compile time. The error "Generic type requires type argument(s)" is TypeScript's way of ensuring you're using types correctly, even if the code would run in JavaScript.
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