add pushTypeResolution to getTypeOfAlias (#52642)

Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
This commit is contained in:
Isabel Duan 2023-10-27 18:08:20 -07:00 committed by GitHub
parent 6061069d96
commit 29cfca319b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 76 additions and 8 deletions

View File

@ -11832,9 +11832,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
function getTypeOfAlias(symbol: Symbol): Type {
const links = getSymbolLinks(symbol);
if (!links.type) {
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
return errorType;
}
const targetSymbol = resolveAlias(symbol);
const exportSymbol = symbol.declarations && getTargetOfAliasDeclaration(getDeclarationOfAliasSymbol(symbol)!, /*dontRecursivelyResolve*/ true);
const declaredType = firstDefined(exportSymbol?.declarations, d => isExportAssignment(d) ? tryGetTypeFromEffectiveTypeNode(d) : undefined);
// It only makes sense to get the type of a value symbol. If the result of resolving
// the alias is not a value, then it has no type. To get the type associated with a
// type symbol, call getDeclaredTypeOfSymbol.
@ -11845,6 +11849,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
: declaredType ? declaredType
: getSymbolFlags(targetSymbol) & SymbolFlags.Value ? getTypeOfSymbol(targetSymbol)
: errorType;
if (!popTypeResolution()) {
reportCircularityError(exportSymbol ?? symbol);
return links.type = errorType;
}
}
return links.type;
}
@ -11860,15 +11869,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function reportCircularityError(symbol: Symbol) {
const declaration = symbol.valueDeclaration as VariableLikeDeclaration;
const declaration = symbol.valueDeclaration;
// Check if variable has type annotation that circularly references the variable itself
if (getEffectiveTypeAnnotationNode(declaration)) {
error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
return errorType;
if (declaration) {
if (getEffectiveTypeAnnotationNode(declaration)) {
error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
return errorType;
}
// Check if variable has initializer that circularly references the variable itself
if (noImplicitAny && (declaration.kind !== SyntaxKind.Parameter || (declaration as HasInitializer).initializer)) {
error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, symbolToString(symbol));
}
}
// Check if variable has initializer that circularly references the variable itself
if (noImplicitAny && (declaration.kind !== SyntaxKind.Parameter || (declaration as HasInitializer).initializer)) {
error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, symbolToString(symbol));
else if (symbol.flags & SymbolFlags.Alias) {
const node = getDeclarationOfAliasSymbol(symbol);
if (node) {
error(node, Diagnostics.Circular_definition_of_import_alias_0, symbolToString(symbol));
}
}
// Circularities could also result from parameters in function expressions that end up
// having themselves as contextual types following type argument inference. In those cases

View File

@ -0,0 +1,11 @@
bar.js(2,1): error TS2303: Circular definition of import alias 'blah'.
bar.js(2,24): error TS2339: Property 'someProp' does not exist on type '{ (): void; blah: any; }'.
==== bar.js (2 errors) ====
module.exports = function () {};
exports.blah = exports.someProp;
~~~~~~~~~~~~
!!! error TS2303: Circular definition of import alias 'blah'.
~~~~~~~~
!!! error TS2339: Property 'someProp' does not exist on type '{ (): void; blah: any; }'.

View File

@ -0,0 +1,14 @@
//// [tests/cases/compiler/pushTypeGetTypeOfAlias.ts] ////
=== bar.js ===
module.exports = function () {};
>module.exports : Symbol(module.exports, Decl(bar.js, 0, 0))
>module : Symbol(export=, Decl(bar.js, 0, 0))
>exports : Symbol(export=, Decl(bar.js, 0, 0))
exports.blah = exports.someProp;
>exports.blah : Symbol(blah, Decl(bar.js, 0, 32))
>exports : Symbol(blah, Decl(bar.js, 0, 32))
>blah : Symbol(blah, Decl(bar.js, 0, 32))
>exports : Symbol("bar", Decl(bar.js, 0, 0))

View File

@ -0,0 +1,19 @@
//// [tests/cases/compiler/pushTypeGetTypeOfAlias.ts] ////
=== bar.js ===
module.exports = function () {};
>module.exports = function () {} : { (): void; blah: any; }
>module.exports : { (): void; blah: any; }
>module : { exports: { (): void; blah: any; }; }
>exports : { (): void; blah: any; }
>function () {} : () => void
exports.blah = exports.someProp;
>exports.blah = exports.someProp : any
>exports.blah : any
>exports : { (): void; blah: any; }
>blah : any
>exports.someProp : any
>exports : { (): void; blah: any; }
>someProp : any

View File

@ -16,7 +16,7 @@ import self = require("recursiveExportAssignmentAndFindAliasedType7_moduleD");
var selfVar = self;
>selfVar : any
>self : any
>self : error
export = selfVar;
>selfVar : any

View File

@ -0,0 +1,7 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @Filename: bar.js
module.exports = function () {};
exports.blah = exports.someProp;