diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b9f33abe6c8..5b85a932c05 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -115,7 +115,7 @@ namespace ts { const intersectionTypes = createMap(); const stringLiteralTypes = createMap(); const numericLiteralTypes = createMap(); - const evolvingArrayTypes: AnonymousType[] = []; + const evolvingArrayTypes: EvolvingArrayType[] = []; const unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown"); const resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__"); @@ -323,9 +323,9 @@ namespace ts { "undefined": undefinedType }); - let jsxElementType: ObjectType; + let jsxElementType: Type; /** Things we lazy load from the JSX namespace */ - const jsxTypes = createMap(); + const jsxTypes = createMap(); const JsxNames = { JSX: "JSX", IntrinsicElements: "IntrinsicElements", @@ -538,6 +538,10 @@ namespace ts { return nodeLinks[nodeId] || (nodeLinks[nodeId] = { flags: 0 }); } + function getObjectFlags(type: Type): ObjectFlags { + return type.flags & TypeFlags.Object ? (type).objectFlags : 0; + } + function isGlobalSourceFile(node: Node) { return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node); } @@ -1589,8 +1593,9 @@ namespace ts { return type; } - function createObjectType(kind: TypeFlags, symbol?: Symbol): ObjectType { - const type = createType(kind); + function createObjectType(objectFlags: ObjectFlags, symbol?: Symbol): ObjectType { + const type = createType(TypeFlags.Object); + type.objectFlags = objectFlags; type.symbol = symbol; return type; } @@ -1620,7 +1625,7 @@ namespace ts { return result || emptyArray; } - function setObjectTypeMembers(type: ObjectType, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): ResolvedType { + function setStructuredTypeMembers(type: StructuredType, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): ResolvedType { (type).members = members; (type).properties = getNamedMembers(members); (type).callSignatures = callSignatures; @@ -1631,7 +1636,7 @@ namespace ts { } function createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): ResolvedType { - return setObjectTypeMembers(createObjectType(TypeFlags.Anonymous, symbol), + return setStructuredTypeMembers(createObjectType(ObjectFlags.Anonymous, symbol), members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } @@ -2182,7 +2187,7 @@ namespace ts { } writer.writeKeyword("this"); } - else if (type.flags & TypeFlags.Reference) { + else if (getObjectFlags(type) & ObjectFlags.Reference) { writeTypeReference(type, nextFlags); } else if (type.flags & TypeFlags.EnumLiteral) { @@ -2190,11 +2195,11 @@ namespace ts { writePunctuation(writer, SyntaxKind.DotToken); appendSymbolNameOnly(type.symbol, writer); } - else if (type.flags & (TypeFlags.Class | TypeFlags.Interface | TypeFlags.Enum | TypeFlags.TypeParameter)) { + else if (getObjectFlags(type) & ObjectFlags.ClassOrInterface || type.flags & (TypeFlags.Enum | TypeFlags.TypeParameter)) { // The specified symbol flags need to be reinterpreted as type flags buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags); } - else if (!(flags & TypeFormatFlags.InTypeAlias) && ((type.flags & TypeFlags.Anonymous && !(type).target) || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol && + else if (!(flags & TypeFormatFlags.InTypeAlias) && ((getObjectFlags(type) & ObjectFlags.Anonymous && !(type).target) || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol && isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) { // We emit inferred type as type-alias at the current localtion if all the following is true // the input type is has alias symbol that is accessible @@ -2208,7 +2213,7 @@ namespace ts { else if (type.flags & TypeFlags.UnionOrIntersection) { writeUnionOrIntersectionType(type, nextFlags); } - else if (type.flags & TypeFlags.Anonymous) { + else if (getObjectFlags(type) & ObjectFlags.Anonymous) { writeAnonymousType(type, nextFlags); } else if (type.flags & TypeFlags.StringOrNumberLiteral) { @@ -2264,7 +2269,7 @@ namespace ts { writePunctuation(writer, SyntaxKind.OpenBracketToken); writePunctuation(writer, SyntaxKind.CloseBracketToken); } - else if (type.target.flags & TypeFlags.Tuple) { + else if (type.target.objectFlags & ObjectFlags.Tuple) { writePunctuation(writer, SyntaxKind.OpenBracketToken); writeTypeList(type.typeArguments.slice(0, getTypeReferenceArity(type)), SyntaxKind.CommaToken); writePunctuation(writer, SyntaxKind.CloseBracketToken); @@ -2866,7 +2871,6 @@ namespace ts { return getSymbolLinks(target).declaredType; } if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) { - Debug.assert(!!((target).flags & TypeFlags.Class)); return (target).resolvedBaseConstructorType; } if (propertyName === TypeSystemPropertyName.ResolvedReturnType) { @@ -3218,7 +3222,7 @@ namespace ts { result.pattern = pattern; } if (hasComputedProperties) { - result.isObjectLiteralPatternWithComputedProperties = true; + result.objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties; } return result; } @@ -3456,7 +3460,7 @@ namespace ts { links.type = anyType; } else { - const type = createObjectType(TypeFlags.Anonymous, symbol); + const type = createObjectType(ObjectFlags.Anonymous, symbol); links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ? includeFalsyTypes(type, TypeFlags.Undefined) : type; } @@ -3519,8 +3523,8 @@ namespace ts { return unknownType; } - function getTargetType(type: ObjectType): Type { - return type.flags & TypeFlags.Reference ? (type).target : type; + function getTargetType(type: Type): Type { + return getObjectFlags(type) & ObjectFlags.Reference ? (type).target : type; } function hasBaseType(type: InterfaceType, checkBase: InterfaceType) { @@ -3596,20 +3600,20 @@ namespace ts { } function isConstructorType(type: Type): boolean { - return type.flags & TypeFlags.ObjectType && getSignaturesOfType(type, SignatureKind.Construct).length > 0; + return type.flags & TypeFlags.Object && getSignaturesOfType(type, SignatureKind.Construct).length > 0; } function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments { return getClassExtendsHeritageClauseElement(type.symbol.valueDeclaration); } - function getConstructorsForTypeArguments(type: ObjectType, typeArgumentNodes: TypeNode[]): Signature[] { + function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: TypeNode[]): Signature[] { const typeArgCount = typeArgumentNodes ? typeArgumentNodes.length : 0; return filter(getSignaturesOfType(type, SignatureKind.Construct), sig => (sig.typeParameters ? sig.typeParameters.length : 0) === typeArgCount); } - function getInstantiatedConstructorsForTypeArguments(type: ObjectType, typeArgumentNodes: TypeNode[]): Signature[] { + function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: TypeNode[]): Signature[] { let signatures = getConstructorsForTypeArguments(type, typeArgumentNodes); if (typeArgumentNodes) { const typeArguments = map(typeArgumentNodes, getTypeFromTypeNodeNoAlias); @@ -3623,7 +3627,7 @@ namespace ts { // unknownType if an error occurred during resolution of the extends expression, // nullType if the extends expression is the null value, or // an object type with at least one construct signature. - function getBaseConstructorTypeOfClass(type: InterfaceType): ObjectType { + function getBaseConstructorTypeOfClass(type: InterfaceType): Type { if (!type.resolvedBaseConstructorType) { const baseTypeNode = getBaseTypeNodeOfClass(type); if (!baseTypeNode) { @@ -3633,10 +3637,10 @@ namespace ts { return unknownType; } const baseConstructorType = checkExpression(baseTypeNode.expression); - if (baseConstructorType.flags & TypeFlags.ObjectType) { + if (baseConstructorType.flags & TypeFlags.Object) { // Resolving the members of a class requires us to resolve the base class of that class. // We force resolution here such that we catch circularities now. - resolveStructuredTypeMembers(baseConstructorType); + resolveStructuredTypeMembers(baseConstructorType); } if (!popTypeResolution()) { error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol)); @@ -3653,7 +3657,7 @@ namespace ts { function getBaseTypes(type: InterfaceType): ObjectType[] { if (!type.resolvedBaseTypes) { - if (type.flags & TypeFlags.Tuple) { + if (type.objectFlags & ObjectFlags.Tuple) { type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters))]; } else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { @@ -3673,8 +3677,8 @@ namespace ts { function resolveBaseTypesOfClass(type: InterfaceType): void { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; - const baseConstructorType = getBaseConstructorTypeOfClass(type); - if (!(baseConstructorType.flags & TypeFlags.ObjectType)) { + const baseConstructorType = getBaseConstructorTypeOfClass(type); + if (!(baseConstructorType.flags & TypeFlags.Object)) { return; } const baseTypeNode = getBaseTypeNodeOfClass(type); @@ -3701,7 +3705,7 @@ namespace ts { if (baseType === unknownType) { return; } - if (!(getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface))) { + if (!(getObjectFlags(getTargetType(baseType)) & ObjectFlags.ClassOrInterface)) { error(baseTypeNode.expression, Diagnostics.Base_constructor_return_type_0_is_not_a_class_or_interface_type, typeToString(baseType)); return; } @@ -3711,10 +3715,10 @@ namespace ts { return; } if (type.resolvedBaseTypes === emptyArray) { - type.resolvedBaseTypes = [baseType]; + type.resolvedBaseTypes = [baseType]; } else { - type.resolvedBaseTypes.push(baseType); + type.resolvedBaseTypes.push(baseType); } } @@ -3737,13 +3741,13 @@ namespace ts { for (const node of getInterfaceBaseTypeNodes(declaration)) { const baseType = getTypeFromTypeNode(node); if (baseType !== unknownType) { - if (getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface)) { + if (getObjectFlags(getTargetType(baseType)) & ObjectFlags.ClassOrInterface) { if (type !== baseType && !hasBaseType(baseType, type)) { if (type.resolvedBaseTypes === emptyArray) { - type.resolvedBaseTypes = [baseType]; + type.resolvedBaseTypes = [baseType]; } else { - type.resolvedBaseTypes.push(baseType); + type.resolvedBaseTypes.push(baseType); } } else { @@ -3787,7 +3791,7 @@ namespace ts { function getDeclaredTypeOfClassOrInterface(symbol: Symbol): InterfaceType { const links = getSymbolLinks(symbol); if (!links.declaredType) { - const kind = symbol.flags & SymbolFlags.Class ? TypeFlags.Class : TypeFlags.Interface; + const kind = symbol.flags & SymbolFlags.Class ? ObjectFlags.Class : ObjectFlags.Interface; const type = links.declaredType = createObjectType(kind, symbol); const outerTypeParameters = getOuterTypeParametersOfClassOrInterface(symbol); const localTypeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); @@ -3796,8 +3800,8 @@ namespace ts { // property types inferred from initializers and method return types inferred from return statements are very hard // to exhaustively analyze). We give interfaces a "this" type if we can't definitely determine that they are free of // "this" references. - if (outerTypeParameters || localTypeParameters || kind === TypeFlags.Class || !isIndependentInterface(symbol)) { - type.flags |= TypeFlags.Reference; + if (outerTypeParameters || localTypeParameters || kind === ObjectFlags.Class || !isIndependentInterface(symbol)) { + type.objectFlags |= ObjectFlags.Reference; type.typeParameters = concatenate(outerTypeParameters, localTypeParameters); type.outerTypeParameters = outerTypeParameters; type.localTypeParameters = localTypeParameters; @@ -4093,8 +4097,8 @@ namespace ts { return type; } - function getTypeWithThisArgument(type: ObjectType, thisArgument?: Type) { - if (type.flags & TypeFlags.Reference) { + function getTypeWithThisArgument(type: Type, thisArgument?: Type) { + if (getObjectFlags(type) & ObjectFlags.Reference) { return createTypeReference((type).target, concatenate((type).typeArguments, [thisArgument || (type).target.thisType])); } @@ -4131,7 +4135,7 @@ namespace ts { } const thisArgument = lastOrUndefined(typeArguments); for (const baseType of baseTypes) { - const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType; + const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType; addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType)); callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call)); constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct)); @@ -4139,7 +4143,7 @@ namespace ts { numberIndexInfo = numberIndexInfo || getIndexInfoOfType(instantiatedBaseType, IndexKind.Number); } } - setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } function resolveClassOrInterfaceMembers(type: InterfaceType): void { @@ -4286,7 +4290,7 @@ namespace ts { const constructSignatures = getUnionSignatures(type.types, SignatureKind.Construct); const stringIndexInfo = getUnionIndexInfo(type.types, IndexKind.String); const numberIndexInfo = getUnionIndexInfo(type.types, IndexKind.Number); - setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } function intersectTypes(type1: Type, type2: Type): Type { @@ -4311,7 +4315,7 @@ namespace ts { stringIndexInfo = intersectIndexInfos(stringIndexInfo, getIndexInfoOfType(t, IndexKind.String)); numberIndexInfo = intersectIndexInfos(numberIndexInfo, getIndexInfoOfType(t, IndexKind.Number)); } - setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } function resolveAnonymousTypeMembers(type: AnonymousType) { @@ -4322,7 +4326,7 @@ namespace ts { const constructSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper, instantiateSignature); const stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.String), type.mapper); const numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.Number), type.mapper); - setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } else if (symbol.flags & SymbolFlags.TypeLiteral) { const members = symbol.members; @@ -4330,7 +4334,7 @@ namespace ts { const constructSignatures = getSignaturesOfSymbol(members["__new"]); const stringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); const numberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); - setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } else { // Combinations of function, class, enum and module @@ -4346,13 +4350,13 @@ namespace ts { constructSignatures = getDefaultConstructSignatures(classType); } const baseConstructorType = getBaseConstructorTypeOfClass(classType); - if (baseConstructorType.flags & TypeFlags.ObjectType) { + if (baseConstructorType.flags & TypeFlags.Object) { members = createSymbolTable(getNamedMembers(members)); addInheritedMembers(members, getPropertiesOfObjectType(baseConstructorType)); } } const numberIndexInfo = symbol.flags & SymbolFlags.Enum ? enumNumberIndexInfo : undefined; - setObjectTypeMembers(type, members, emptyArray, constructSignatures, undefined, numberIndexInfo); + setStructuredTypeMembers(type, members, emptyArray, constructSignatures, undefined, numberIndexInfo); // We resolve the members before computing the signatures because a signature may use // typeof with a qualified name expression that circularly references the type we are // in the process of resolving (see issue #6072). The temporarily empty signature list @@ -4363,16 +4367,18 @@ namespace ts { } } - function resolveStructuredTypeMembers(type: ObjectType): ResolvedType { + function resolveStructuredTypeMembers(type: StructuredType): ResolvedType { if (!(type).members) { - if (type.flags & TypeFlags.Reference) { - resolveTypeReferenceMembers(type); - } - else if (type.flags & (TypeFlags.Class | TypeFlags.Interface)) { - resolveClassOrInterfaceMembers(type); - } - else if (type.flags & TypeFlags.Anonymous) { - resolveAnonymousTypeMembers(type); + if (type.flags & TypeFlags.Object) { + if ((type).objectFlags & ObjectFlags.Reference) { + resolveTypeReferenceMembers(type); + } + else if ((type).objectFlags & ObjectFlags.ClassOrInterface) { + resolveClassOrInterfaceMembers(type); + } + else if ((type).objectFlags & ObjectFlags.Anonymous) { + resolveAnonymousTypeMembers(type); + } } else if (type.flags & TypeFlags.Union) { resolveUnionTypeMembers(type); @@ -4386,7 +4392,7 @@ namespace ts { /** Return properties of an object type or an empty array for other types */ function getPropertiesOfObjectType(type: Type): Symbol[] { - if (type.flags & TypeFlags.ObjectType) { + if (type.flags & TypeFlags.Object) { return resolveStructuredTypeMembers(type).properties; } return emptyArray; @@ -4395,7 +4401,7 @@ namespace ts { /** If the given type is an object type and that type has a property by the given name, * return the symbol for that property. Otherwise return undefined. */ function getPropertyOfObjectType(type: Type, name: string): Symbol { - if (type.flags & TypeFlags.ObjectType) { + if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); const symbol = resolved.members[name]; if (symbol && symbolIsValue(symbol)) { @@ -4568,8 +4574,8 @@ namespace ts { */ function getPropertyOfType(type: Type, name: string): Symbol { type = getApparentType(type); - if (type.flags & TypeFlags.ObjectType) { - const resolved = resolveStructuredTypeMembers(type); + if (type.flags & TypeFlags.Object) { + const resolved = resolveStructuredTypeMembers(type); const symbol = resolved.members[name]; if (symbol && symbolIsValue(symbol)) { return symbol; @@ -4927,7 +4933,7 @@ namespace ts { function getRestTypeOfSignature(signature: Signature): Type { if (signature.hasRestParameter) { const type = getTypeOfSymbol(lastOrUndefined(signature.parameters)); - if (type.flags & TypeFlags.Reference && (type).target === globalArrayType) { + if (getObjectFlags(type) & ObjectFlags.Reference && (type).target === globalArrayType) { return (type).typeArguments[0]; } } @@ -4953,7 +4959,7 @@ namespace ts { // will result in a different declaration kind. if (!signature.isolatedSignatureType) { const isConstructor = signature.declaration.kind === SyntaxKind.Constructor || signature.declaration.kind === SyntaxKind.ConstructSignature; - const type = createObjectType(TypeFlags.Anonymous); + const type = createObjectType(ObjectFlags.Anonymous); type.members = emptySymbols; type.properties = emptyArray; type.callSignatures = !isConstructor ? [signature] : emptyArray; @@ -5081,9 +5087,8 @@ namespace ts { const id = getTypeListId(typeArguments); let type = target.instantiations[id]; if (!type) { - const propagatedFlags = typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0; - const flags = TypeFlags.Reference | propagatedFlags; - type = target.instantiations[id] = createObjectType(flags, target.symbol); + type = target.instantiations[id] = createObjectType(ObjectFlags.Reference, target.symbol); + type.flags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0; type.target = target; type.typeArguments = typeArguments; } @@ -5091,7 +5096,9 @@ namespace ts { } function cloneTypeReference(source: TypeReference): TypeReference { - const type = createObjectType(source.flags, source.symbol); + const type = createType(source.flags); + type.symbol = source.symbol; + type.objectFlags = source.objectFlags; type.target = source.target; type.typeArguments = source.typeArguments; return type; @@ -5266,7 +5273,7 @@ namespace ts { return arity ? emptyGenericType : emptyObjectType; } const type = getDeclaredTypeOfSymbol(symbol); - if (!(type.flags & TypeFlags.ObjectType)) { + if (!(type.flags & TypeFlags.Object)) { error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_be_a_class_or_interface_type, symbol.name); return arity ? emptyGenericType : emptyObjectType; } @@ -5316,7 +5323,7 @@ namespace ts { /** * Instantiates a global type that is generic with some element type, and returns that instantiation. */ - function createTypeFromGenericGlobalType(genericGlobalType: GenericType, typeArguments: Type[]): Type { + function createTypeFromGenericGlobalType(genericGlobalType: GenericType, typeArguments: Type[]): ObjectType { return genericGlobalType !== emptyGenericType ? createTypeReference(genericGlobalType, typeArguments) : emptyObjectType; } @@ -5328,7 +5335,7 @@ namespace ts { return createTypeFromGenericGlobalType(getGlobalIterableIteratorType(), [elementType]); } - function createArrayType(elementType: Type): Type { + function createArrayType(elementType: Type): ObjectType { return createTypeFromGenericGlobalType(globalArrayType, [elementType]); } @@ -5357,7 +5364,7 @@ namespace ts { property.type = typeParameter; properties.push(property); } - const type = createObjectType(TypeFlags.Tuple | TypeFlags.Reference); + const type = createObjectType(ObjectFlags.Tuple | ObjectFlags.Reference); type.typeParameters = typeParameters; type.outerTypeParameters = undefined; type.localTypeParameters = typeParameters; @@ -5446,7 +5453,8 @@ namespace ts { const len = typeSet.length; const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearchTypes(typeSet, type); if (index < 0) { - if (!(flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) { + if (!(flags & TypeFlags.Object && (type).objectFlags & ObjectFlags.Anonymous && + type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) { typeSet.splice(~index, 0, type); } } @@ -5568,7 +5576,7 @@ namespace ts { let type = unionTypes[id]; if (!type) { const propagatedFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable); - type = unionTypes[id] = createObjectType(TypeFlags.Union | propagatedFlags); + type = unionTypes[id] = createType(TypeFlags.Union | propagatedFlags); type.types = types; type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = aliasTypeArguments; @@ -5639,7 +5647,7 @@ namespace ts { let type = intersectionTypes[id]; if (!type) { const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable); - type = intersectionTypes[id] = createObjectType(TypeFlags.Intersection | propagatedFlags); + type = intersectionTypes[id] = createType(TypeFlags.Intersection | propagatedFlags); type.types = typeSet; type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = aliasTypeArguments; @@ -5659,7 +5667,7 @@ namespace ts { const links = getNodeLinks(node); if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers - const type = createObjectType(TypeFlags.Anonymous, node.symbol); + const type = createObjectType(ObjectFlags.Anonymous, node.symbol); type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = aliasTypeArguments; links.resolvedType = type; @@ -5980,7 +5988,7 @@ namespace ts { function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): ObjectType { if (mapper.instantiations) { - const cachedType = mapper.instantiations[type.id]; + const cachedType = mapper.instantiations[type.id]; if (cachedType) { return cachedType; } @@ -5989,7 +5997,7 @@ namespace ts { mapper.instantiations = []; } // Mark the anonymous type as instantiated such that our infinite instantiation detection logic can recognize it - const result = createObjectType(TypeFlags.Anonymous | TypeFlags.Instantiated, type.symbol); + const result = createObjectType(ObjectFlags.Anonymous | ObjectFlags.Instantiated, type.symbol); result.target = type; result.mapper = mapper; result.aliasSymbol = type.aliasSymbol; @@ -6052,20 +6060,22 @@ namespace ts { if (type.flags & TypeFlags.TypeParameter) { return mapper(type); } - if (type.flags & TypeFlags.Anonymous) { - // If the anonymous type originates in a declaration of a function, method, class, or - // interface, in an object type literal, or in an object literal expression, we may need - // to instantiate the type because it might reference a type parameter. We skip instantiation - // if none of the type parameters that are in scope in the type's declaration are mapped by - // the given mapper, however we can only do that analysis if the type isn't itself an - // instantiation. - return type.symbol && - type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && - (type.flags & TypeFlags.Instantiated || isSymbolInScopeOfMappedTypeParameter(type.symbol, mapper)) ? - instantiateAnonymousType(type, mapper) : type; - } - if (type.flags & TypeFlags.Reference) { - return createTypeReference((type).target, instantiateList((type).typeArguments, mapper, instantiateType)); + if (type.flags & TypeFlags.Object) { + if ((type).objectFlags & ObjectFlags.Anonymous) { + // If the anonymous type originates in a declaration of a function, method, class, or + // interface, in an object type literal, or in an object literal expression, we may need + // to instantiate the type because it might reference a type parameter. We skip instantiation + // if none of the type parameters that are in scope in the type's declaration are mapped by + // the given mapper, however we can only do that analysis if the type isn't itself an + // instantiation. + return type.symbol && + type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && + ((type).objectFlags & ObjectFlags.Instantiated || isSymbolInScopeOfMappedTypeParameter(type.symbol, mapper)) ? + instantiateAnonymousType(type, mapper) : type; + } + if ((type).objectFlags & ObjectFlags.Reference) { + return createTypeReference((type).target, instantiateList((type).typeArguments, mapper, instantiateType)); + } } if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) { return getUnionType(instantiateList((type).types, mapper, instantiateType), /*subtypeReduction*/ false, type.aliasSymbol, mapper.targetTypes); @@ -6137,10 +6147,10 @@ namespace ts { } function getTypeWithoutSignatures(type: Type): Type { - if (type.flags & TypeFlags.ObjectType) { + if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); if (resolved.constructSignatures.length) { - const result = createObjectType(TypeFlags.Anonymous, type.symbol); + const result = createObjectType(ObjectFlags.Anonymous, type.symbol); result.members = resolved.members; result.properties = resolved.properties; result.callSignatures = emptyArray; @@ -6447,7 +6457,7 @@ namespace ts { if (source === target || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) { return true; } - if (source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType) { + if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) { const id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id; const related = relation[id]; if (related !== undefined) { @@ -6479,8 +6489,8 @@ namespace ts { containingMessageChain?: DiagnosticMessageChain): boolean { let errorInfo: DiagnosticMessageChain; - let sourceStack: ObjectType[]; - let targetStack: ObjectType[]; + let sourceStack: Type[]; + let targetStack: Type[]; let maybeStack: Map[]; let expandingFlags: number; let depth = 0; @@ -6556,7 +6566,7 @@ namespace ts { if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True; - if (source.flags & TypeFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) { + if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) { if (hasExcessProperties(source, target, reportErrors)) { if (reportErrors) { reportRelationError(headMessage, source, target); @@ -6635,7 +6645,7 @@ namespace ts { } } else { - if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (source).target === (target).target) { + if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source).target === (target).target) { // We have type references to same target type, see if relationship holds for all type arguments if (result = typeArgumentsRelatedTo(source, target, reportErrors)) { return result; @@ -6647,7 +6657,7 @@ namespace ts { // In a check of the form X = A & B, we will have previously checked if A relates to X or B relates // to X. Failing both of those we want to check if the aggregation of A and B's members structurally // relates to X. Thus, we include intersection types on the source side here. - if (apparentSource.flags & (TypeFlags.ObjectType | TypeFlags.Intersection) && target.flags & TypeFlags.ObjectType) { + if (apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Object) { // Report structural errors only if we haven't reported any errors yet const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !(source.flags & TypeFlags.Primitive); if (result = objectTypeRelatedTo(apparentSource, source, target, reportStructuralErrors)) { @@ -6658,10 +6668,10 @@ namespace ts { } if (reportErrors) { - if (source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.Primitive) { + if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Primitive) { tryElaborateErrorsForPrimitivesAndObjects(source, target); } - else if (source.symbol && source.flags & TypeFlags.ObjectType && globalObjectType === source) { + else if (source.symbol && source.flags & TypeFlags.Object && globalObjectType === source) { reportError(Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); } reportRelationError(headMessage, source, target); @@ -6671,8 +6681,8 @@ namespace ts { function isIdenticalTo(source: Type, target: Type): Ternary { let result: Ternary; - if (source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType) { - if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (source).target === (target).target) { + if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) { + if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source).target === (target).target) { // We have type references to same target type, see if all type arguments are identical if (result = typeArgumentsRelatedTo(source, target, /*reportErrors*/ false)) { return result; @@ -6696,8 +6706,8 @@ namespace ts { // index signatures, or if the property is actually declared in the object type. In a union or intersection // type, a property is considered known if it is known in any constituent type. function isKnownProperty(type: Type, name: string): boolean { - if (type.flags & TypeFlags.ObjectType) { - const resolved = resolveStructuredTypeMembers(type); + if (type.flags & TypeFlags.Object) { + const resolved = resolveStructuredTypeMembers(type); if ((relation === assignableRelation || relation === comparableRelation) && (type === globalObjectType || isEmptyObjectType(resolved)) || resolved.stringIndexInfo || (resolved.numberIndexInfo && isNumericLiteralName(name)) || @@ -6724,8 +6734,7 @@ namespace ts { } function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean { - if (maybeTypeOfKind(target, TypeFlags.ObjectType) && - (!(target.flags & TypeFlags.ObjectType) || !(target as ObjectType).isObjectLiteralPatternWithComputedProperties)) { + if (maybeTypeOfKind(target, TypeFlags.Object) && !(getObjectFlags(target) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) { for (const prop of getPropertiesOfObjectType(source)) { if (!isKnownProperty(target, prop.name)) { if (reportErrors) { @@ -6919,7 +6928,7 @@ namespace ts { } let result = Ternary.True; const properties = getPropertiesOfObjectType(target); - const requireOptionalProperties = relation === subtypeRelation && !(source.flags & TypeFlags.ObjectLiteral); + const requireOptionalProperties = relation === subtypeRelation && !(getObjectFlags(source) & ObjectFlags.ObjectLiteral); for (const targetProp of properties) { const sourceProp = getPropertyOfType(source, targetProp.name); @@ -6998,7 +7007,7 @@ namespace ts { } function propertiesIdenticalTo(source: Type, target: Type): Ternary { - if (!(source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType)) { + if (!(source.flags & TypeFlags.Object && target.flags & TypeFlags.Object)) { return Ternary.False; } const sourceProperties = getPropertiesOfObjectType(source); @@ -7200,7 +7209,7 @@ namespace ts { // Return true if the given type is the constructor type for an abstract class function isAbstractConstructorType(type: Type) { - if (type.flags & TypeFlags.Anonymous) { + if (getObjectFlags(type) & ObjectFlags.Anonymous) { const symbol = type.symbol; if (symbol && symbol.flags & SymbolFlags.Class) { const declaration = getClassLikeDeclarationOfSymbol(symbol); @@ -7219,12 +7228,12 @@ namespace ts { // some level beyond that. function isDeeplyNestedGeneric(type: Type, stack: Type[], depth: number): boolean { // We track type references (created by createTypeReference) and instantiated types (created by instantiateType) - if (type.flags & (TypeFlags.Reference | TypeFlags.Instantiated) && depth >= 5) { + if (getObjectFlags(type) & (ObjectFlags.Reference | ObjectFlags.Instantiated) && depth >= 5) { const symbol = type.symbol; let count = 0; for (let i = 0; i < depth; i++) { const t = stack[i]; - if (t.flags & (TypeFlags.Reference | TypeFlags.Instantiated) && t.symbol === symbol) { + if (getObjectFlags(t) & (ObjectFlags.Reference | ObjectFlags.Instantiated) && t.symbol === symbol) { count++; if (count >= 5) return true; } @@ -7427,13 +7436,13 @@ namespace ts { } function isArrayType(type: Type): boolean { - return type.flags & TypeFlags.Reference && (type).target === globalArrayType; + return getObjectFlags(type) & ObjectFlags.Reference && (type).target === globalArrayType; } function isArrayLikeType(type: Type): boolean { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray - return type.flags & TypeFlags.Reference && ((type).target === globalArrayType || (type).target === globalReadonlyArrayType) || + return getObjectFlags(type) & ObjectFlags.Reference && ((type).target === globalArrayType || (type).target === globalReadonlyArrayType) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); } @@ -7474,7 +7483,7 @@ namespace ts { * Prefer using isTupleLikeType() unless the use of `elementTypes` is required. */ function isTupleType(type: Type): boolean { - return !!(type.flags & TypeFlags.Reference && (type).target.flags & TypeFlags.Tuple); + return !!(getObjectFlags(type) & ObjectFlags.Reference && (type).target.objectFlags & ObjectFlags.Tuple); } function getFalsyFlagsOfTypes(types: Type[]): TypeFlags { @@ -7558,7 +7567,7 @@ namespace ts { * Leave signatures alone since they are not subject to the check. */ function getRegularTypeOfObjectLiteral(type: Type): Type { - if (!(type.flags & TypeFlags.ObjectLiteral && type.flags & TypeFlags.FreshLiteral)) { + if (!(getObjectFlags(type) & ObjectFlags.ObjectLiteral && type.flags & TypeFlags.FreshLiteral)) { return type; } const regularType = (type).regularType; @@ -7575,6 +7584,7 @@ namespace ts { resolved.stringIndexInfo, resolved.numberIndexInfo); regularNew.flags = resolved.flags & ~TypeFlags.FreshLiteral; + regularNew.objectFlags |= ObjectFlags.ObjectLiteral; (type).regularType = regularNew; return regularNew; } @@ -7600,7 +7610,7 @@ namespace ts { if (type.flags & TypeFlags.Nullable) { return anyType; } - if (type.flags & TypeFlags.ObjectLiteral) { + if (getObjectFlags(type) & ObjectFlags.ObjectLiteral) { return getWidenedTypeOfObjectLiteral(type); } if (type.flags & TypeFlags.Union) { @@ -7640,7 +7650,7 @@ namespace ts { } } } - if (type.flags & TypeFlags.ObjectLiteral) { + if (getObjectFlags(type) & ObjectFlags.ObjectLiteral) { for (const p of getPropertiesOfObjectType(type)) { const t = getTypeOfSymbol(p); if (t.flags & TypeFlags.ContainsWideningType) { @@ -7743,8 +7753,8 @@ namespace ts { // results for union and intersection types for performance reasons. function couldContainTypeParameters(type: Type): boolean { return !!(type.flags & TypeFlags.TypeParameter || - type.flags & TypeFlags.Reference && forEach((type).typeArguments, couldContainTypeParameters) || - type.flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) || + getObjectFlags(type) & ObjectFlags.Reference && forEach((type).typeArguments, couldContainTypeParameters) || + getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) || type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeParameters(type)); } @@ -7852,7 +7862,7 @@ namespace ts { } } } - else if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (source).target === (target).target) { + else if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source).target === (target).target) { // If source and target are references to the same generic type, infer from type arguments const sourceTypes = (source).typeArguments || emptyArray; const targetTypes = (target).typeArguments || emptyArray; @@ -7893,7 +7903,7 @@ namespace ts { } else { source = getApparentType(source); - if (source.flags & TypeFlags.ObjectType) { + if (source.flags & TypeFlags.Object) { if (isInProcess(source, target)) { return; } @@ -8285,7 +8295,7 @@ namespace ts { type === falseType ? TypeFacts.FalseStrictFacts : TypeFacts.TrueStrictFacts : type === falseType ? TypeFacts.FalseFacts : TypeFacts.TrueFacts; } - if (flags & TypeFlags.ObjectType) { + if (flags & TypeFlags.Object) { return isFunctionObjectType(type) ? strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts : strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; @@ -8547,28 +8557,24 @@ namespace ts { // 'x.push(value)' or 'x[n] = value' operation along the control flow graph. Evolving // array types are ultimately converted into manifest array types (using getFinalArrayType) // and never escape the getFlowTypeOfReference function. - function createEvolvingArrayType(elementType: Type): AnonymousType { - const result = createObjectType(TypeFlags.Anonymous); + function createEvolvingArrayType(elementType: Type): EvolvingArrayType { + const result = createObjectType(ObjectFlags.EvolvingArray); result.elementType = elementType; return result; } - function getEvolvingArrayType(elementType: Type): AnonymousType { + function getEvolvingArrayType(elementType: Type): EvolvingArrayType { return evolvingArrayTypes[elementType.id] || (evolvingArrayTypes[elementType.id] = createEvolvingArrayType(elementType)); } // When adding evolving array element types we do not perform subtype reduction. Instead, // we defer subtype reduction until the evolving array type is finalized into a manifest // array type. - function addEvolvingArrayElementType(evolvingArrayType: AnonymousType, node: Expression): AnonymousType { + function addEvolvingArrayElementType(evolvingArrayType: EvolvingArrayType, node: Expression): EvolvingArrayType { const elementType = getBaseTypeOfLiteralType(checkExpression(node)); return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType])); } - function isEvolvingArrayType(type: Type) { - return !!(type.flags & TypeFlags.Anonymous && (type).elementType); - } - function createFinalArrayType(elementType: Type) { return elementType.flags & TypeFlags.Never ? autoArrayType : @@ -8578,23 +8584,23 @@ namespace ts { } // We perform subtype reduction upon obtaining the final array type from an evolving array type. - function getFinalArrayType(evolvingArrayType: AnonymousType): Type { + function getFinalArrayType(evolvingArrayType: EvolvingArrayType): Type { return evolvingArrayType.finalArrayType || (evolvingArrayType.finalArrayType = createFinalArrayType(evolvingArrayType.elementType)); } function finalizeEvolvingArrayType(type: Type): Type { - return isEvolvingArrayType(type) ? getFinalArrayType(type) : type; + return getObjectFlags(type) & ObjectFlags.EvolvingArray ? getFinalArrayType(type) : type; } function getElementTypeOfEvolvingArrayType(type: Type) { - return isEvolvingArrayType(type) ? (type).elementType : neverType; + return getObjectFlags(type) & ObjectFlags.EvolvingArray ? (type).elementType : neverType; } function isEvolvingArrayTypeList(types: Type[]) { let hasEvolvingArrayType = false; for (const t of types) { if (!(t.flags & TypeFlags.Never)) { - if (!isEvolvingArrayType(t)) { + if (!(getObjectFlags(t) & ObjectFlags.EvolvingArray)) { return false; } hasEvolvingArrayType = true; @@ -8645,7 +8651,7 @@ namespace ts { // we give type 'any[]' to 'x' instead of using the type determined by control flow analysis such that operations // on empty arrays are possible without implicit any errors and new element types can be inferred without // type mismatch errors. - const resultType = isEvolvingArrayType(evolvedType) && isEvolvingArrayOperationTarget(reference) ? anyArrayType : finalizeEvolvingArrayType(evolvedType); + const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? anyArrayType : finalizeEvolvingArrayType(evolvedType); if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) { return declaredType; } @@ -8758,8 +8764,8 @@ namespace ts { if (isMatchingReference(reference, getReferenceCandidate(expr))) { const flowType = getTypeAtFlowNode(flow.antecedent); const type = getTypeFromFlowType(flowType); - if (isEvolvingArrayType(type)) { - let evolvedType = type; + if (getObjectFlags(type) & ObjectFlags.EvolvingArray) { + let evolvedType = type; if (node.kind === SyntaxKind.CallExpression) { for (const arg of (node).arguments) { evolvedType = addEvolvingArrayElementType(evolvedType, arg); @@ -9101,10 +9107,10 @@ namespace ts { if (!targetType) { // Target type is type of construct signature let constructSignatures: Signature[]; - if (rightType.flags & TypeFlags.Interface) { + if (getObjectFlags(rightType) & ObjectFlags.Interface) { constructSignatures = resolveDeclaredMembers(rightType).declaredConstructSignatures; } - else if (rightType.flags & TypeFlags.Anonymous) { + else if (getObjectFlags(rightType) & ObjectFlags.Anonymous) { constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct); } if (constructSignatures && constructSignatures.length) { @@ -10588,8 +10594,7 @@ namespace ts { patternWithComputedProperties = true; } } - else if (contextualTypeHasPattern && - !(contextualType.flags & TypeFlags.ObjectType && (contextualType as ObjectType).isObjectLiteralPatternWithComputedProperties)) { + else if (contextualTypeHasPattern && !(getObjectFlags(contextualType) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) { // 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); @@ -10654,9 +10659,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); + result.flags |= TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags); + result.objectFlags |= ObjectFlags.ObjectLiteral; if (patternWithComputedProperties) { - result.isObjectLiteralPatternWithComputedProperties = true; + result.objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties; } if (inDestructuringPattern) { result.pattern = node; @@ -11239,7 +11245,7 @@ namespace ts { } // TODO: why is the first part of this check here? - if (!(getTargetType(type).flags & (TypeFlags.Class | TypeFlags.Interface) && hasBaseType(type, enclosingClass))) { + if (!(getObjectFlags(getTargetType(type)) & ObjectFlags.ClassOrInterface && hasBaseType(type, enclosingClass))) { error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass)); return false; } @@ -11726,7 +11732,7 @@ namespace ts { // If type has a single call signature and no other members, return that signature. Otherwise, return undefined. function getSingleCallSignature(type: Type): Signature { - if (type.flags & TypeFlags.ObjectType) { + if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 && resolved.properties.length === 0 && !resolved.stringIndexInfo && !resolved.numberIndexInfo) { @@ -13528,7 +13534,7 @@ namespace ts { } function isConstEnumObjectType(type: Type): boolean { - return type.flags & (TypeFlags.ObjectType | TypeFlags.Anonymous) && type.symbol && isConstEnumSymbol(type.symbol); + return getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && isConstEnumSymbol(type.symbol); } function isConstEnumSymbol(symbol: Symbol): boolean { @@ -13565,7 +13571,7 @@ namespace ts { if (!isTypeAnyOrAllConstituentTypesHaveKind(leftType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol); } - if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.ObjectType | TypeFlags.TypeParameter)) { + if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeParameter)) { error(right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } return booleanType; @@ -15293,7 +15299,7 @@ namespace ts { return undefined; } - if (promise.flags & TypeFlags.Reference) { + if (getObjectFlags(promise) & ObjectFlags.Reference) { if ((promise).target === tryGetGlobalPromiseType() || (promise).target === getGlobalPromiseLikeType()) { return (promise).typeArguments[0]; @@ -16488,7 +16494,7 @@ namespace ts { const rightType = checkNonNullExpression(node.expression); // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one - if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.ObjectType | TypeFlags.TypeParameter)) { + if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeParameter)) { error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter); } @@ -16578,7 +16584,7 @@ namespace ts { if (!typeAsIterable.iterableElementType) { // As an optimization, if the type is instantiated directly using the globalIterableType (Iterable), // then just grab its type argument. - if ((type.flags & TypeFlags.Reference) && (type).target === getGlobalIterableType()) { + if ((getObjectFlags(type) & ObjectFlags.Reference) && (type).target === getGlobalIterableType()) { typeAsIterable.iterableElementType = (type).typeArguments[0]; } else { @@ -16624,7 +16630,7 @@ namespace ts { if (!typeAsIterator.iteratorElementType) { // As an optimization, if the type is instantiated directly using the globalIteratorType (Iterator), // then just grab its type argument. - if ((type.flags & TypeFlags.Reference) && (type).target === getGlobalIteratorType()) { + if ((getObjectFlags(type) & ObjectFlags.Reference) && (type).target === getGlobalIteratorType()) { typeAsIterator.iteratorElementType = (type).typeArguments[0]; } else { @@ -16668,7 +16674,7 @@ namespace ts { // As an optimization, if the type is instantiated directly using the globalIterableIteratorType (IterableIterator), // then just grab its type argument. - if ((type.flags & TypeFlags.Reference) && (type).target === getGlobalIterableIteratorType()) { + if ((getObjectFlags(type) & ObjectFlags.Reference) && (type).target === getGlobalIterableIteratorType()) { return (type).typeArguments[0]; } @@ -16965,7 +16971,7 @@ namespace ts { checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number); }); - if (type.flags & TypeFlags.Class && isClassLike(type.symbol.valueDeclaration)) { + if (getObjectFlags(type) & ObjectFlags.Class && isClassLike(type.symbol.valueDeclaration)) { const classDeclaration = type.symbol.valueDeclaration; for (const member of classDeclaration.members) { // Only process instance properties with computed names here. @@ -16984,7 +16990,7 @@ namespace ts { if (stringIndexType && numberIndexType) { errorNode = declaredNumberIndexer || declaredStringIndexer; // condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer - if (!errorNode && (type.flags & TypeFlags.Interface)) { + if (!errorNode && (getObjectFlags(type) & ObjectFlags.Interface)) { const someBaseTypeHasBothIndexers = forEach(getBaseTypes(type), base => getIndexTypeOfType(base, IndexKind.String) && getIndexTypeOfType(base, IndexKind.Number)); errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0]; } @@ -17021,7 +17027,7 @@ namespace ts { else if (indexDeclaration) { errorNode = indexDeclaration; } - else if (containingType.flags & TypeFlags.Interface) { + else if (getObjectFlags(containingType) & ObjectFlags.Interface) { // for interfaces property and indexer might be inherited from different bases // check if any base class already has both property and indexer. // check should be performed only if 'type' is the first type that brings property\indexer together @@ -17180,8 +17186,8 @@ namespace ts { if (produceDiagnostics) { const t = getTypeFromTypeNode(typeRefNode); if (t !== unknownType) { - const declaredType = (t.flags & TypeFlags.Reference) ? (t).target : t; - if (declaredType.flags & (TypeFlags.Class | TypeFlags.Interface)) { + const declaredType = getObjectFlags(t) & ObjectFlags.Reference ? (t).target : t; + if (getObjectFlags(declaredType) & ObjectFlags.ClassOrInterface) { checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(t, type.thisType), node.name || node, Diagnostics.Class_0_incorrectly_implements_interface_1); } else { @@ -17198,7 +17204,7 @@ namespace ts { } } - function checkBaseTypeAccessibility(type: ObjectType, node: ExpressionWithTypeArguments) { + function checkBaseTypeAccessibility(type: Type, node: ExpressionWithTypeArguments) { const signatures = getSignaturesOfType(type, SignatureKind.Construct); if (signatures.length) { const declaration = signatures[0].declaration; @@ -19256,7 +19262,7 @@ namespace ts { } function isFunctionType(type: Type): boolean { - return type.flags & TypeFlags.ObjectType && getSignaturesOfType(type, SignatureKind.Call).length > 0; + return type.flags & TypeFlags.Object && getSignaturesOfType(type, SignatureKind.Call).length > 0; } function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind { @@ -19688,7 +19694,7 @@ namespace ts { const thenPropertySymbol = createSymbol(SymbolFlags.Transient | SymbolFlags.Property, "then"); getSymbolLinks(thenPropertySymbol).type = globalFunctionType; - const thenableType = createObjectType(TypeFlags.Anonymous); + const thenableType = createObjectType(ObjectFlags.Anonymous); thenableType.properties = [thenPropertySymbol]; thenableType.members = createSymbolTable(thenableType.properties); thenableType.callSignatures = []; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index dd1878f36a7..f9ec3e9f268 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2612,24 +2612,17 @@ namespace ts { Null = 1 << 12, Never = 1 << 13, // Never type TypeParameter = 1 << 14, // Type parameter - Class = 1 << 15, // Class - Interface = 1 << 16, // Interface - Reference = 1 << 17, // Generic type reference - Tuple = 1 << 18, // Synthesized generic tuple type - Union = 1 << 19, // Union (T | U) - Intersection = 1 << 20, // Intersection (T & U) - Anonymous = 1 << 21, // Anonymous - Instantiated = 1 << 22, // Instantiated anonymous type + Object = 1 << 15, // Object type + Union = 1 << 16, // Union (T | U) + Intersection = 1 << 17, // Intersection (T & U) /* @internal */ - ObjectLiteral = 1 << 23, // Originates in an object literal + FreshLiteral = 1 << 18, // Fresh literal type /* @internal */ - FreshLiteral = 1 << 24, // Fresh literal type + ContainsWideningType = 1 << 19, // Type is or contains undefined or null widening type /* @internal */ - ContainsWideningType = 1 << 25, // Type is or contains undefined or null widening type + ContainsObjectLiteral = 1 << 20, // Type is or contains object literal type /* @internal */ - ContainsObjectLiteral = 1 << 26, // Type is or contains object literal type - /* @internal */ - ContainsAnyFunctionType = 1 << 27, // Type is or contains object literal type + ContainsAnyFunctionType = 1 << 21, // Type is or contains object literal type /* @internal */ Nullable = Undefined | Null, @@ -2646,15 +2639,14 @@ namespace ts { NumberLike = Number | NumberLiteral | Enum | EnumLiteral, BooleanLike = Boolean | BooleanLiteral, EnumLike = Enum | EnumLiteral, - ObjectType = Class | Interface | Reference | Tuple | Anonymous, UnionOrIntersection = Union | Intersection, - StructuredType = ObjectType | Union | Intersection, + StructuredType = Object | Union | Intersection, StructuredOrTypeParameter = StructuredType | TypeParameter, // 'Narrowable' types are types where narrowing actually narrows. // This *should* be every type other than null, undefined, void, and never Narrowable = Any | StructuredType | TypeParameter | StringLike | NumberLike | BooleanLike | ESSymbol, - NotUnionOrUnit = Any | ESSymbol | ObjectType, + NotUnionOrUnit = Any | ESSymbol | Object, /* @internal */ RequiresWidening = ContainsWideningType | ContainsObjectLiteral, /* @internal */ @@ -2697,9 +2689,22 @@ namespace ts { baseType: EnumType & UnionType; // Base enum type } + export const enum ObjectFlags { + Class = 1 << 0, // Class + Interface = 1 << 1, // Interface + Reference = 1 << 2, // Generic type reference + Tuple = 1 << 3, // Synthesized generic tuple type + Anonymous = 1 << 4, // Anonymous + Instantiated = 1 << 5, // Instantiated anonymous type + ObjectLiteral = 1 << 6, // Originates in an object literal + EvolvingArray = 1 << 7, // Evolving array type + ObjectLiteralPatternWithComputedProperties = 1 << 8, // Object literal pattern with computed properties + ClassOrInterface = Class | Interface + } + // Object types (TypeFlags.ObjectType) export interface ObjectType extends Type { - isObjectLiteralPatternWithComputedProperties?: boolean; + objectFlags: ObjectFlags; } // Class and interface types (TypeFlags.Class and TypeFlags.Interface) @@ -2753,13 +2758,18 @@ namespace ts { export interface IntersectionType extends UnionOrIntersectionType { } + export type StructuredType = ObjectType | UnionType | IntersectionType; + /* @internal */ // An instantiated anonymous type has a target and a mapper export interface AnonymousType extends ObjectType { target?: AnonymousType; // Instantiation target mapper?: TypeMapper; // Instantiation mapper - elementType?: Type; // Element expressions of evolving array type - finalArrayType?: Type; // Final array type of evolving array type + } + + export interface EvolvingArrayType extends ObjectType { + elementType: Type; // Element expressions of evolving array type + finalArrayType?: Type; // Final array type of evolving array type } /* @internal */ diff --git a/src/services/services.ts b/src/services/services.ts index 06e8a4615f9..5669134d37e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -347,6 +347,7 @@ namespace ts { class TypeObject implements Type { checker: TypeChecker; flags: TypeFlags; + objectFlags?: ObjectFlags; id: number; symbol: Symbol; constructor(checker: TypeChecker, flags: TypeFlags) { @@ -381,7 +382,7 @@ namespace ts { return this.checker.getIndexTypeOfType(this, IndexKind.Number); } getBaseTypes(): ObjectType[] { - return this.flags & (TypeFlags.Class | TypeFlags.Interface) + return this.flags & TypeFlags.Object && this.objectFlags & (ObjectFlags.Class | ObjectFlags.Interface) ? this.checker.getBaseTypes(this) : undefined; } diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index c9141278b10..516b5d7fbc5 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -173,7 +173,7 @@ namespace ts.SymbolDisplay { displayParts.push(keywordPart(SyntaxKind.NewKeyword)); displayParts.push(spacePart()); } - if (!(type.flags & TypeFlags.Anonymous) && type.symbol) { + if (!(type.flags & TypeFlags.Object && (type).objectFlags & ObjectFlags.Anonymous) && type.symbol) { addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments)); } addSignatureDisplayParts(signature, allSignatures, TypeFormatFlags.WriteArrowStyleSignature);