Skip to content

Commit 7d88700

Browse files
JoostKdylhunn
authored andcommitted
fix(compiler-cli): accept inheriting the constructor from a class in a library (#48156)
The stricter checks under `strictInjectionParameters` in Angular 15 now enforce that an inherited constructor must be compatible with DI, based on whether all parameters are valid injection tokens. There is an issue when the constructor is inherited from a class in a declaration file though, as information on the usage of `@Inject()` is not present within a declaration file. This means that this stricter check cannot be accurately performed, resulting in false positives. This commit disables the stricter check to behave the same as it did prior to Angular 15, therefore avoiding the false positive. Fixes #48152 PR Close #48156
1 parent 2e38af1 commit 7d88700

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

packages/compiler-cli/src/ngtsc/annotations/common/src/diagnostics.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {DirectiveMeta, flattenInheritedDirectiveMetadata, HostDirectiveMeta, Met
1414
import {describeResolvedType, DynamicValue, PartialEvaluator, ResolvedValue, traceDynamicValue} from '../../../partial_evaluator';
1515
import {ClassDeclaration, ReflectionHost} from '../../../reflection';
1616
import {DeclarationData, LocalModuleScopeRegistry} from '../../../scope';
17-
import {identifierOfNode} from '../../../util/src/typescript';
17+
import {identifierOfNode, isFromDtsFile} from '../../../util/src/typescript';
1818

1919
import {InjectableClassRegistry} from './injectable_registry';
2020
import {isAbstractClassDeclaration, readBaseClass} from './util';
@@ -256,6 +256,14 @@ export function checkInheritanceOfInjectable(
256256
return getInheritedUndecoratedCtorDiagnostic(node, classWithCtor.ref, kind);
257257
}
258258

259+
if (isFromDtsFile(classWithCtor.ref.node)) {
260+
// The inherited class is declared in a declaration file, in which case there is not enough
261+
// information to detect invalid constructors as `@Inject()` metadata is not present in the
262+
// declaration file. Consequently, we have to accept such occurrences, although they might
263+
// still fail at runtime.
264+
return null;
265+
}
266+
259267
if (!strictInjectionParameters || isAbstractClassDeclaration(node)) {
260268
// An invalid constructor is only reported as error under `strictInjectionParameters` and
261269
// only for concrete classes; follow the same exclusions for derived types.

packages/compiler-cli/test/ngtsc/ngtsc_spec.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2960,6 +2960,37 @@ function allTests(os: string) {
29602960
`or add an explicit constructor to ConcreteDirWithoutCtor.`);
29612961
expect(getDiagnosticSourceCode(diags[2])).toBe('ConcreteDirWithoutCtor');
29622962
});
2963+
2964+
// https://github.com/angular/angular/issues/48152
2965+
it('should not give a compile-time error when a class inherits from foreign compilation unit',
2966+
() => {
2967+
env.tsconfig({strictInjectionParameters: true});
2968+
env.write('node_modules/external/index.d.ts', `
2969+
import * as i0 from '@angular/core';
2970+
2971+
export abstract class ExternalClass {
2972+
static ɵprov: i0.ɵɵInjectableDeclaration<ExternalClass>;
2973+
static ɵfac: i0.ɵɵFactoryDeclaration<ExternalClass, never>
2974+
2975+
constructor(invalid: string) {}
2976+
}
2977+
`);
2978+
env.write('test.ts', `
2979+
import {Directive} from '@angular/core';
2980+
import {ExternalClass} from 'external';
2981+
2982+
@Directive()
2983+
export abstract class AbstractMiddleDir extends ExternalClass {}
2984+
2985+
@Directive()
2986+
export class ConcreteMiddleDir extends AbstractMiddleDir {}
2987+
2988+
@Directive()
2989+
export class ConcreteDirWithoutCtor extends ConcreteMiddleDir {}
2990+
`);
2991+
2992+
env.driveMain();
2993+
});
29632994
});
29642995

29652996
describe('with strictInjectionParameters = false', () => {

0 commit comments

Comments
 (0)