diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bf7e4ef92e6..422f2a70dcc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2165,7 +2165,7 @@ namespace ts { ? "any" : (type).intrinsicName); } - else if (type.flags & TypeFlags.ThisType) { + else if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) { if (inObjectTypeLiteral) { writer.reportInaccessibleThisError(); } @@ -3179,7 +3179,7 @@ namespace ts { result.pattern = pattern; } if (hasComputedProperties) { - result.flags |= TypeFlags.ObjectLiteralPatternWithComputedProperties; + result.isObjectLiteralPatternWithComputedProperties = true; } return result; } @@ -3766,7 +3766,8 @@ namespace ts { (type).instantiations[getTypeListId(type.typeParameters)] = type; (type).target = type; (type).typeArguments = type.typeParameters; - type.thisType = createType(TypeFlags.TypeParameter | TypeFlags.ThisType); + type.thisType = createType(TypeFlags.TypeParameter); + type.thisType.isThisType = true; type.thisType.symbol = symbol; type.thisType.constraint = type; } @@ -4968,7 +4969,7 @@ namespace ts { function hasConstraintReferenceTo(type: Type, target: TypeParameter): boolean { let checked: Type[]; - while (type && !(type.flags & TypeFlags.ThisType) && type.flags & TypeFlags.TypeParameter && !contains(checked, type)) { + while (type && type.flags & TypeFlags.TypeParameter && !((type as TypeParameter).isThisType) && !contains(checked, type)) { if (type === target) { return true; } @@ -5331,7 +5332,8 @@ namespace ts { type.instantiations[getTypeListId(type.typeParameters)] = type; type.target = type; type.typeArguments = type.typeParameters; - type.thisType = createType(TypeFlags.TypeParameter | TypeFlags.ThisType); + type.thisType = createType(TypeFlags.TypeParameter); + type.thisType.isThisType = true; type.thisType.constraint = type; type.declaredProperties = properties; type.declaredCallSignatures = emptyArray; @@ -6647,7 +6649,8 @@ namespace ts { } function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean { - if (!(target.flags & TypeFlags.ObjectLiteralPatternWithComputedProperties) && maybeTypeOfKind(target, TypeFlags.ObjectType)) { + if (maybeTypeOfKind(target, TypeFlags.ObjectType) && + (!(target.flags & TypeFlags.ObjectType) || !(target as ObjectType).isObjectLiteralPatternWithComputedProperties)) { for (const prop of getPropertiesOfObjectType(source)) { if (!isKnownProperty(target, prop.name)) { if (reportErrors) { @@ -10307,7 +10310,8 @@ namespace ts { patternWithComputedProperties = true; } } - else if (contextualTypeHasPattern && !(contextualType.flags & TypeFlags.ObjectLiteralPatternWithComputedProperties)) { + else if (contextualTypeHasPattern && + !(contextualType.flags & TypeFlags.ObjectType && (contextualType as ObjectType).isObjectLiteralPatternWithComputedProperties)) { // If object literal is contextually typed by the implied type of a binding pattern, and if the // binding pattern specifies a default value for the property, make the property optional. const impliedProp = getPropertyOfType(contextualType, member.name); @@ -10372,7 +10376,10 @@ namespace ts { const numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node, propertiesArray, IndexKind.Number) : undefined; const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral; - result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags) | (patternWithComputedProperties ? TypeFlags.ObjectLiteralPatternWithComputedProperties : 0); + result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags); + if (patternWithComputedProperties) { + result.isObjectLiteralPatternWithComputedProperties = true; + } if (inDestructuringPattern) { result.pattern = node; } @@ -10942,7 +10949,7 @@ namespace ts { return true; } // An instance property must be accessed through an instance of the enclosing class - if (type.flags & TypeFlags.ThisType) { + if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) { // get the original type -- represented as the type constraint of the 'this' type type = getConstraintOfTypeParameter(type); } @@ -10992,7 +10999,7 @@ namespace ts { const prop = getPropertyOfType(apparentType, right.text); if (!prop) { if (right.text && !checkAndReportErrorForExtendingInterface(node)) { - reportNonexistentProperty(right, type.flags & TypeFlags.ThisType ? apparentType : type); + reportNonexistentProperty(right, type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType ? apparentType : type); } return unknownType; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f6d79176992..4a4a25fd627 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2393,8 +2393,6 @@ namespace ts { ContainsObjectLiteral = 1 << 26, // Type is or contains object literal type /* @internal */ ContainsAnyFunctionType = 1 << 27, // Type is or contains object literal type - ThisType = 1 << 28, // This type - ObjectLiteralPatternWithComputedProperties = 1 << 29, // Object literal type implied by binding pattern has computed properties /* @internal */ Nullable = Undefined | Null, @@ -2463,7 +2461,9 @@ namespace ts { } // Object types (TypeFlags.ObjectType) - export interface ObjectType extends Type { } + export interface ObjectType extends Type { + isObjectLiteralPatternWithComputedProperties?: boolean; + } // Class and interface types (TypeFlags.Class and TypeFlags.Interface) export interface InterfaceType extends ObjectType { @@ -2558,6 +2558,8 @@ namespace ts { mapper?: TypeMapper; // Instantiation mapper /* @internal */ resolvedApparentType: Type; + /* @internal */ + isThisType?: boolean; } export const enum SignatureKind {