Dont look for properties of Object and Function type when looking to resolve named import from module with export= (#37964)

* Add tests

* Dont look at object or function type when looking for members of `export=` type to be resolved by named imports
Fixes #37165

* Create separate cache when skipping function and object property augmentation

* Lookup in both cache if not skipObjectFunctionPropertyAugment
This commit is contained in:
Sheetal Nandi
2020-11-03 12:22:30 -08:00
committed by GitHub
parent b00870ead4
commit 9c60d5a4d3
11 changed files with 291 additions and 12 deletions
+15 -11
View File
@@ -2689,7 +2689,7 @@ namespace ts {
let symbolFromVariable: Symbol | undefined;
// First check if module was specified with "export=". If so, get the member from the resolved type
if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get(InternalSymbolName.ExportEquals)) {
symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.escapedText);
symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.escapedText, /*skipObjectFunctionPropertyAugment*/ true);
}
else {
symbolFromVariable = getPropertyOfVariable(targetSymbol, name.escapedText);
@@ -11147,7 +11147,7 @@ namespace ts {
return getReducedType(getApparentType(getReducedType(type)));
}
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String): Symbol | undefined {
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined {
let singleProp: Symbol | undefined;
let propSet: ESMap<SymbolId, Symbol> | undefined;
let indexTypes: Type[] | undefined;
@@ -11159,7 +11159,7 @@ namespace ts {
for (const current of containingType.types) {
const type = getApparentType(current);
if (!(type === errorType || type.flags & TypeFlags.Never)) {
const prop = getPropertyOfType(type, name);
const prop = getPropertyOfType(type, name, skipObjectFunctionPropertyAugment);
const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0;
if (prop) {
if (isUnion) {
@@ -11276,20 +11276,23 @@ namespace ts {
// constituents, in which case the isPartial flag is set when the containing type is union type. We need
// these partial properties when identifying discriminant properties, but otherwise they are filtered out
// and do not appear to be present in the union type.
function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: __String): Symbol | undefined {
const properties = type.propertyCache || (type.propertyCache = createSymbolTable());
let property = properties.get(name);
function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined {
let property = type.propertyCacheWithoutObjectFunctionPropertyAugment?.get(name) ||
!skipObjectFunctionPropertyAugment ? type.propertyCache?.get(name) : undefined;
if (!property) {
property = createUnionOrIntersectionProperty(type, name);
property = createUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment);
if (property) {
const properties = skipObjectFunctionPropertyAugment ?
type.propertyCacheWithoutObjectFunctionPropertyAugment ||= createSymbolTable() :
type.propertyCache ||= createSymbolTable();
properties.set(name, property);
}
}
return property;
}
function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: __String): Symbol | undefined {
const property = getUnionOrIntersectionProperty(type, name);
function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined {
const property = getUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment);
// We need to filter out partial properties in union types
return property && !(getCheckFlags(property) & CheckFlags.ReadPartial) ? property : undefined;
}
@@ -11367,7 +11370,7 @@ namespace ts {
* @param type a type to look up property from
* @param name a name of property to look up in a given type
*/
function getPropertyOfType(type: Type, name: __String): Symbol | undefined {
function getPropertyOfType(type: Type, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined {
type = getReducedApparentType(type);
if (type.flags & TypeFlags.Object) {
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
@@ -11375,6 +11378,7 @@ namespace ts {
if (symbol && symbolIsValue(symbol)) {
return symbol;
}
if (skipObjectFunctionPropertyAugment) return undefined;
const functionType = resolved === anyFunctionType ? globalFunctionType :
resolved.callSignatures.length ? globalCallableFunctionType :
resolved.constructSignatures.length ? globalNewableFunctionType :
@@ -11388,7 +11392,7 @@ namespace ts {
return getPropertyOfObjectType(globalObjectType, name);
}
if (type.flags & TypeFlags.UnionOrIntersection) {
return getPropertyOfUnionOrIntersectionType(<UnionOrIntersectionType>type, name);
return getPropertyOfUnionOrIntersectionType(<UnionOrIntersectionType>type, name, skipObjectFunctionPropertyAugment);
}
return undefined;
}
+3 -1
View File
@@ -5193,7 +5193,9 @@ namespace ts {
/* @internal */
objectFlags: ObjectFlags;
/* @internal */
propertyCache: SymbolTable; // Cache of resolved properties
propertyCache?: SymbolTable; // Cache of resolved properties
/* @internal */
propertyCacheWithoutObjectFunctionPropertyAugment?: SymbolTable; // Cache of resolved properties that does not augment function or object type properties
/* @internal */
resolvedProperties: Symbol[];
/* @internal */