The Problem
Angular's Ivy compiler performs stricter type checking than the old View Engine. Generic type constraints that worked before Ivy now cause compilation errors during ng build or ng serve.
Symptoms
- Build fails with TypeScript generic type errors
- "Type does not satisfy the constraint" during compilation
- Errors in generic components, services, or pipes
- Works in one Angular version but fails after upgrade
Real Error Message
Error: src/app/components/data-table.component.ts:23:14 - error NG2005:
The class 'DataTableComponent' is using an unsupported feature.
Type 'T' does not satisfy the constraint 'Record<string, unknown>'.Common Causes
Cause 1: Unconstrained Generic in Component
// WRONG: T has no constraint
@Component({...})
export class DataTableComponent<T> {
@Input() data: T[] = [];
}Ivy requires generics to have constraints.
Cause 2: Generic Service Without Proper Injection
// WRONG: Generic providedIn with runtime resolution
@Injectable({ providedIn: 'root' })
export class DataService<T> {
getAll(): Observable<T[]> {
return this.http.get<T[]>(`/api/${this.endpoint}`);
}
}How to Fix It
Fix 1: Add Generic Type Constraint
@Component({...})
export class DataTableComponent<T extends Record<string, unknown>> {
@Input() data: T[] = [];
}Fix 2: Use Type Parameter in Module
```typescript @NgModule({ declarations: [], exports: [DataTableComponent] }) export class DataTableModule {}
// Usage in template <app-data-table [data]="users"></app-data-table> ```
Fix 3: Generic Service with Factory
```typescript @Injectable() export class DataService<T> { constructor( protected http: HttpClient, protected endpoint: string ) {}
getAll(): Observable<T[]> { return this.http.get<T[]>(this.endpoint); } }
// Concrete service @Injectable({ providedIn: 'root' }) export class UserService extends DataService<User> { constructor(http: HttpClient) { super(http, '/api/users'); } } ```
Fix 4: Disable Strict Generic Checks (Temporary)
// tsconfig.json
{
"angularCompilerOptions": {
"strictTemplates": false,
"strictInjectionParameters": false
}
}This is a temporary workaround. Fix the type constraints properly.
Fix 5: Use any as Last Resort
@Component({...})
export class DataTableComponent {
@Input() data: any[] = [];
}