diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/type_check_file.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/type_check_file.ts index eadc68b5fd..9f1fb7c708 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/type_check_file.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/type_check_file.ts @@ -59,6 +59,11 @@ export class TypeCheckFile extends Environment { source += printer.printNode(ts.EmitHint.Unspecified, stmt, this.contextFile) + '\n'; } + // Ensure the template type-checking file is an ES module. Otherwise, it's interpreted as some + // kind of global namespace in TS, which forces a full re-typecheck of the user's program that + // is somehow more expensive than the initial parse. + source += '\nexport const IS_A_MODULE = true;\n'; + return ts.createSourceFile( this.fileName, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS); } diff --git a/packages/compiler-cli/src/ngtsc/typecheck/test/type_constructor_spec.ts b/packages/compiler-cli/src/ngtsc/typecheck/test/type_constructor_spec.ts index 36744e9b42..0cf603313f 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/test/type_constructor_spec.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/test/type_constructor_spec.ts @@ -13,12 +13,14 @@ import {TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflectio import {getDeclaration, makeProgram} from '../../testing'; import {getRootDirs} from '../../util/src/typescript'; import {TypeCheckContext} from '../src/context'; +import {TypeCheckFile} from '../src/type_check_file'; import {ALL_ENABLED_CONFIG} from './test_utils'; runInEachFileSystem(() => { describe('ngtsc typechecking', () => { let _: typeof absoluteFrom; let LIB_D_TS: TestFile; + let TYPE_CHECK_TS: TestFile; beforeEach(() => { _ = absoluteFrom; @@ -29,12 +31,25 @@ runInEachFileSystem(() => { type Pick = { [P in K]: T[P]; }; type NonNullable = T extends null | undefined ? never : T;` }; + TYPE_CHECK_TS = { + name: _('/_typecheck_.ts'), + contents: ` + export const IS_A_MODULE = true; + ` + }; + }); + + it('should not produce an empty SourceFile when there is nothing to typecheck', () => { + const file = + new TypeCheckFile(_('/_typecheck_.ts'), ALL_ENABLED_CONFIG, new ReferenceEmitter([])); + const sf = file.render(); + expect(sf.statements.length).toBe(1); }); describe('ctors', () => { it('compiles a basic type constructor', () => { const files: TestFile[] = [ - LIB_D_TS, { + LIB_D_TS, TYPE_CHECK_TS, { name: _('/main.ts'), contents: ` class TestClass { @@ -72,7 +87,7 @@ TestClass.ngTypeCtor({value: 'test'}); it('should not consider query fields', () => { const files: TestFile[] = [ - LIB_D_TS, { + LIB_D_TS, TYPE_CHECK_TS, { name: _('/main.ts'), contents: `class TestClass { value: any; }`, }