In Ivy's template type checker, type constructors are created for all directive types to allow for accurate type inference to work. The type checker has two strategies for dealing with such type constructors: 1. They can be emitted local to the type check block/type check file. 2. They can be emitted as static `ngTypeCtor` field into the directive itself. The first strategy is preferred, as it avoids having to update the directive type which would cause a more expensive rebuild. However, this strategy is not suitable for directives that have constrained generic types, as those constraints would need to be present on the local type constructor declaration. This is not trivial, as it requires that any type references within a type parameter's constraint are imported into the local context of the type check block. For example, lets consider the `NgForOf` directive from '@angular/core' looks as follows: ```typescript import {NgIterable} from '@angular/core'; export class NgForOf<T, U extends NgIterable<T>> {} ``` The type constructor will then have the signature: `(o: Pick<i1.NgForOf<T, U>, 'ngForOf'>) => i1.NgForOf<T, U>` Notice how this refers to the type parameters `T` and `U`, so the type constructor needs to be emitted into a scope where those types are available, _and_ have the correct constraints. Previously, the template type checker would detect the situation where a type parameter is constrained, and would emit the type constructor using strategy 2; within the directive type itself. This approach makes any type references within the generic type constraints lexically available: ```typescript export class NgForOf<T, U extends NgIterable<T>> { static ngTypeCtor<T = any, U extends NgIterable<T> = any> (o: Pick<NgForOf<T, U>, 'ngForOf'>): NgForOf<T, U> { return null!; } } ``` This commit introduces the ability to emit a type parameter with constraints into a different context, under the condition that it can be imported from an absolute module. This allows a generic type constructor to be emitted into a type check block or type check file according to strategy 1, as imports have been generated for all type references within generic type constraints. For example: ```typescript import * as i0 from '@angular/core'; import * as i1 from '@angular/common'; const _ctor1: <T = any, U extends i0.NgIterable<T> = any> (o: Pick<i1.NgForOf<T, U>, 'ngForOf'>) => i1.NgForOf<T, U> = null!; ``` Notice how the generic type constraint of `U` has resulted in an import of `@angular/core`, and the `NgIterable` is transformed into a qualified name during the emitting process. Resolves FW-1739 PR Close #34021
Angular
The sources for this package are in the main Angular repo. Please file issues and pull requests against that repo.
Usage information and reference details can be found in Angular documentation.
License: MIT