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

bash
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

typescript
// 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

typescript
// 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

typescript
@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)

json
// tsconfig.json
{
  "angularCompilerOptions": {
    "strictTemplates": false,
    "strictInjectionParameters": false
  }
}

This is a temporary workaround. Fix the type constraints properly.

Fix 5: Use any as Last Resort

typescript
@Component({...})
export class DataTableComponent {
  @Input() data: any[] = [];
}