diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0dce8cf8eca..3bd089aff6f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -390,10 +390,10 @@ namespace ts { const wildcardType = createIntrinsicType(TypeFlags.Any, "any"); const errorType = createIntrinsicType(TypeFlags.Any, "error"); const unknownType = createIntrinsicType(TypeFlags.Unknown, "unknown"); - const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined"); - const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsWideningType, "undefined"); - const nullType = createIntrinsicType(TypeFlags.Null, "null"); - const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsWideningType, "null"); + const undefinedType = createNullableType(TypeFlags.Undefined, "undefined", 0); + const undefinedWideningType = strictNullChecks ? undefinedType : createNullableType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType); + const nullType = createNullableType(TypeFlags.Null, "null", 0); + const nullWideningType = strictNullChecks ? nullType : createNullableType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType); const stringType = createIntrinsicType(TypeFlags.String, "string"); const numberType = createIntrinsicType(TypeFlags.Number, "number"); const bigintType = createIntrinsicType(TypeFlags.BigInt, "bigint"); @@ -439,7 +439,7 @@ namespace ts { const anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); // The anyFunctionType contains the anyFunctionType by definition. The flag is further propagated // in getPropagatingFlagsOfTypes, and it is checked in inferFromTypes. - anyFunctionType.flags |= TypeFlags.ContainsAnyFunctionType; + anyFunctionType.objectFlags |= ObjectFlags.ContainsAnyFunctionType; const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const circularConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -2753,6 +2753,12 @@ namespace ts { return type; } + function createNullableType(kind: TypeFlags, intrinsicName: string, objectFlags: ObjectFlags): NullableType { + const type = createIntrinsicType(kind, intrinsicName); + type.objectFlags = objectFlags; + return type; + } + function createBooleanType(trueFalseTypes: ReadonlyArray): IntrinsicType & UnionType { const type = getUnionType(trueFalseTypes); type.flags |= TypeFlags.Boolean; @@ -5140,7 +5146,7 @@ namespace ts { definedInConstructor = true; } } - const sourceTypes = some(constructorTypes, t => !!(t.flags & ~(TypeFlags.Nullable | TypeFlags.ContainsWideningType))) ? constructorTypes : types; // TODO: GH#18217 + const sourceTypes = some(constructorTypes, t => !!(t.flags & ~TypeFlags.Nullable)) ? constructorTypes : types; // TODO: GH#18217 type = getUnionType(sourceTypes!, UnionReduction.Subtype); } const widened = getWidenedType(addOptionality(type, definedInMethod && !definedInConstructor)); @@ -5305,7 +5311,7 @@ namespace ts { function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { const members = createSymbolTable(); let stringIndexInfo: IndexInfo | undefined; - let objectFlags = ObjectFlags.ObjectLiteral; + let objectFlags = ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectLiteral; forEach(pattern.elements, e => { const name = e.propertyName || e.name; if (e.dotDotDotToken) { @@ -5327,7 +5333,6 @@ namespace ts { members.set(symbol.escapedName, symbol); }); const result = createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, undefined); - result.flags |= TypeFlags.ContainsObjectLiteral; result.objectFlags |= objectFlags; if (includePatternInType) { result.pattern = pattern; @@ -8552,14 +8557,14 @@ namespace ts { // It is only necessary to do so if a constituent type might be the undefined type, the null type, the type // of an object literal or the anyFunctionType. This is because there are operations in the type checker // that care about the presence of such types at arbitrary depth in a containing type. - function getPropagatingFlagsOfTypes(types: ReadonlyArray, excludeKinds: TypeFlags): TypeFlags { - let result: TypeFlags = 0; + function getPropagatingFlagsOfTypes(types: ReadonlyArray, excludeKinds: TypeFlags): ObjectFlags { + let result: ObjectFlags = 0; for (const type of types) { if (!(type.flags & excludeKinds)) { - result |= type.flags; + result |= getObjectFlags(type); } } - return result & TypeFlags.PropagatingFlags; + return result & ObjectFlags.PropagatingFlags; } function createTypeReference(target: GenericType, typeArguments: ReadonlyArray | undefined): TypeReference { @@ -8568,7 +8573,7 @@ namespace ts { if (!type) { type = createObjectType(ObjectFlags.Reference, target.symbol); target.instantiations.set(id, type); - type.flags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0; + type.objectFlags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0; type.target = target; type.typeArguments = typeArguments; } @@ -9247,10 +9252,11 @@ namespace ts { // intersections of unit types into 'never' upon construction, but deferring the reduction makes it // easier to reason about their origin. if (!(flags & TypeFlags.Never || flags & TypeFlags.Intersection && isEmptyIntersectionType(type))) { - includes |= flags & ~TypeFlags.ConstructionFlags; - if (type === wildcardType) includes |= TypeFlags.Wildcard; + includes |= flags & TypeFlags.IncludesMask; + if (flags & TypeFlags.StructuredOrInstantiable) includes |= TypeFlags.IncludesStructuredOrInstantiable; + if (type === wildcardType) includes |= TypeFlags.IncludesWildcard; if (!strictNullChecks && flags & TypeFlags.Nullable) { - if (!(flags & TypeFlags.ContainsWideningType)) includes |= TypeFlags.NonWideningType; + if (!(getObjectFlags(type) & ObjectFlags.ContainsWideningType)) includes |= TypeFlags.IncludesNonWideningType; } else { const len = typeSet.length; @@ -9361,27 +9367,27 @@ namespace ts { const includes = addTypesToUnion(typeSet, 0, types); if (unionReduction !== UnionReduction.None) { if (includes & TypeFlags.AnyOrUnknown) { - return includes & TypeFlags.Any ? includes & TypeFlags.Wildcard ? wildcardType : anyType : unknownType; + return includes & TypeFlags.Any ? includes & TypeFlags.IncludesWildcard ? wildcardType : anyType : unknownType; } switch (unionReduction) { case UnionReduction.Literal: - if (includes & TypeFlags.StringOrNumberLiteralOrUnique | TypeFlags.BooleanLiteral) { + if (includes & (TypeFlags.Literal | TypeFlags.UniqueESSymbol)) { removeRedundantLiteralTypes(typeSet, includes); } break; case UnionReduction.Subtype: - if (!removeSubtypes(typeSet, !(includes & TypeFlags.StructuredOrInstantiable))) { + if (!removeSubtypes(typeSet, !(includes & TypeFlags.IncludesStructuredOrInstantiable))) { return errorType; } break; } if (typeSet.length === 0) { - return includes & TypeFlags.Null ? includes & TypeFlags.NonWideningType ? nullType : nullWideningType : - includes & TypeFlags.Undefined ? includes & TypeFlags.NonWideningType ? undefinedType : undefinedWideningType : + return includes & TypeFlags.Null ? includes & TypeFlags.IncludesNonWideningType ? nullType : nullWideningType : + includes & TypeFlags.Undefined ? includes & TypeFlags.IncludesNonWideningType ? undefinedType : undefinedWideningType : neverType; } } - return getUnionTypeFromSortedList(typeSet, !(includes & TypeFlags.NotPrimitiveUnion), aliasSymbol, aliasTypeArguments); + return getUnionTypeFromSortedList(typeSet, includes & TypeFlags.NotPrimitiveUnion ? 0 : ObjectFlags.PrimitiveUnion, aliasSymbol, aliasTypeArguments); } function getUnionTypePredicate(signatures: ReadonlyArray): TypePredicate | undefined { @@ -9421,7 +9427,7 @@ namespace ts { } // This function assumes the constituent type list is sorted and deduplicated. - function getUnionTypeFromSortedList(types: Type[], primitiveTypesOnly: boolean, aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray): Type { + function getUnionTypeFromSortedList(types: Type[], objectFlags: ObjectFlags, aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray): Type { if (types.length === 0) { return neverType; } @@ -9431,11 +9437,10 @@ namespace ts { const id = getTypeListId(types); let type = unionTypes.get(id); if (!type) { - const propagatedFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable); - type = createType(TypeFlags.Union | propagatedFlags); + type = createType(TypeFlags.Union); unionTypes.set(id, type); + type.objectFlags = objectFlags | getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable); type.types = types; - type.primitiveTypesOnly = primitiveTypesOnly; /* Note: This is the alias symbol (or lack thereof) that we see when we first encounter this union type. For aliases of identical unions, eg `type T = A | B; type U = A | B`, the symbol of the first alias encountered is the aliasSymbol. @@ -9464,15 +9469,15 @@ namespace ts { return addTypesToIntersection(typeSet, includes, (type).types); } if (isEmptyAnonymousObjectType(type)) { - if (!(includes & TypeFlags.EmptyObject)) { - includes |= TypeFlags.EmptyObject; + if (!(includes & TypeFlags.IncludesEmptyObject)) { + includes |= TypeFlags.IncludesEmptyObject; typeSet.push(type); } } else { - includes |= flags & ~TypeFlags.ConstructionFlags; + includes |= flags & TypeFlags.IncludesMask; if (flags & TypeFlags.AnyOrUnknown) { - if (type === wildcardType) includes |= TypeFlags.Wildcard; + if (type === wildcardType) includes |= TypeFlags.IncludesWildcard; } else if ((strictNullChecks || !(flags & TypeFlags.Nullable)) && !contains(typeSet, type)) { typeSet.push(type); @@ -9530,7 +9535,7 @@ namespace ts { // other unions and return true. Otherwise, do nothing and return false. function intersectUnionsOfPrimitiveTypes(types: Type[]) { let unionTypes: UnionType[] | undefined; - const index = findIndex(types, t => !!(t.flags & TypeFlags.Union) && (t).primitiveTypesOnly); + const index = findIndex(types, t => !!(getObjectFlags(t) & ObjectFlags.PrimitiveUnion)); if (index < 0) { return false; } @@ -9539,7 +9544,7 @@ namespace ts { // the unionTypes array. while (i < types.length) { const t = types[i]; - if (t.flags & TypeFlags.Union && (t).primitiveTypesOnly) { + if (getObjectFlags(t) & ObjectFlags.PrimitiveUnion) { (unionTypes || (unionTypes = [types[index]])).push(t); orderedRemoveItemAt(types, i); } @@ -9566,7 +9571,7 @@ namespace ts { } } // Finally replace the first union with the result - types[index] = getUnionTypeFromSortedList(result, /*primitiveTypesOnly*/ true); + types[index] = getUnionTypeFromSortedList(result, ObjectFlags.PrimitiveUnion); return true; } @@ -9587,7 +9592,7 @@ namespace ts { return neverType; } if (includes & TypeFlags.Any) { - return includes & TypeFlags.Wildcard ? wildcardType : anyType; + return includes & TypeFlags.IncludesWildcard ? wildcardType : anyType; } if (!strictNullChecks && includes & TypeFlags.Nullable) { return includes & TypeFlags.Undefined ? undefinedType : nullType; @@ -9598,7 +9603,7 @@ namespace ts { includes & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol) { removeRedundantPrimitiveTypes(typeSet, includes); } - if (includes & TypeFlags.EmptyObject && includes & TypeFlags.Object) { + if (includes & TypeFlags.IncludesEmptyObject && includes & TypeFlags.Object) { orderedRemoveItemAt(typeSet, findIndex(typeSet, isEmptyAnonymousObjectType)); } if (typeSet.length === 0) { @@ -9624,9 +9629,9 @@ namespace ts { const id = getTypeListId(typeSet); let type = intersectionTypes.get(id); if (!type) { - const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable); - type = createType(TypeFlags.Intersection | propagatedFlags); + type = createType(TypeFlags.Intersection); intersectionTypes.set(id, type); + type.objectFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable); type.types = typeSet; type.aliasSymbol = aliasSymbol; // See comment in `getUnionTypeFromSortedList`. type.aliasTypeArguments = aliasTypeArguments; @@ -10285,7 +10290,7 @@ namespace ts { * this function should be called in a left folding style, with left = previous result of getSpreadType * and right = the new element to be spread. */ - function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, typeFlags: TypeFlags, objectFlags: ObjectFlags, readonly: boolean): Type { + function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, objectFlags: ObjectFlags, readonly: boolean): Type { if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } @@ -10299,10 +10304,10 @@ namespace ts { return left; } if (left.flags & TypeFlags.Union) { - return mapType(left, t => getSpreadType(t, right, symbol, typeFlags, objectFlags, readonly)); + return mapType(left, t => getSpreadType(t, right, symbol, objectFlags, readonly)); } if (right.flags & TypeFlags.Union) { - return mapType(right, t => getSpreadType(left, t, symbol, typeFlags, objectFlags, readonly)); + return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly)); } if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) { return left; @@ -10319,7 +10324,7 @@ namespace ts { const types = (left).types; const lastLeft = types[types.length - 1]; if (isNonGenericObjectType(lastLeft) && isNonGenericObjectType(right)) { - return getIntersectionType(concatenate(types.slice(0, types.length - 1), [getSpreadType(lastLeft, right, symbol, typeFlags, objectFlags, readonly)])); + return getIntersectionType(concatenate(types.slice(0, types.length - 1), [getSpreadType(lastLeft, right, symbol, objectFlags, readonly)])); } } return getIntersectionType([left, right]); @@ -10379,8 +10384,7 @@ namespace ts { emptyArray, getIndexInfoWithReadonly(stringIndexInfo, readonly), getIndexInfoWithReadonly(numberIndexInfo, readonly)); - spread.flags |= TypeFlags.ContainsObjectLiteral | typeFlags; - spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsSpread | objectFlags; + spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectLiteral | ObjectFlags.ContainsSpread | objectFlags; return spread; } @@ -13865,7 +13869,7 @@ namespace ts { resolved.stringIndexInfo, resolved.numberIndexInfo); regularNew.flags = resolved.flags; - regularNew.objectFlags |= ObjectFlags.ObjectLiteral | (getObjectFlags(resolved) & ObjectFlags.JSLiteral); + regularNew.objectFlags |= resolved.objectFlags & ~ObjectFlags.FreshLiteral; (type).regularType = regularNew; return regularNew; } @@ -13956,7 +13960,7 @@ namespace ts { } function getWidenedTypeWithContext(type: Type, context: WideningContext | undefined): Type { - if (type.flags & TypeFlags.RequiresWidening) { + if (getObjectFlags(type) & ObjectFlags.RequiresWidening) { if (type.flags & TypeFlags.Nullable) { return anyType; } @@ -13994,7 +13998,7 @@ namespace ts { */ function reportWideningErrorsInType(type: Type): boolean { let errorReported = false; - if (type.flags & TypeFlags.ContainsWideningType) { + if (getObjectFlags(type) & ObjectFlags.ContainsWideningType) { if (type.flags & TypeFlags.Union) { if (some((type).types, isEmptyObjectType)) { errorReported = true; @@ -14017,7 +14021,7 @@ namespace ts { if (isObjectLiteralType(type)) { for (const p of getPropertiesOfObjectType(type)) { const t = getTypeOfSymbol(p); - if (t.flags & TypeFlags.ContainsWideningType) { + if (getObjectFlags(t) & ObjectFlags.ContainsWideningType) { if (!reportWideningErrorsInType(t)) { error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t))); } @@ -14092,7 +14096,7 @@ namespace ts { } function reportErrorsFromWidening(declaration: Declaration, type: Type) { - if (produceDiagnostics && noImplicitAny && type.flags & TypeFlags.ContainsWideningType) { + if (produceDiagnostics && noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType) { // Report implicit any error within type if possible, otherwise report error on declaration if (!reportWideningErrorsInType(type)) { reportImplicitAny(declaration, type); @@ -14237,7 +14241,7 @@ namespace ts { // If any property contains context sensitive functions that have been skipped, the source type // is incomplete and we can't infer a meaningful input type. for (const prop of properties) { - if (getTypeOfSymbol(prop).flags & TypeFlags.ContainsAnyFunctionType) { + if (getObjectFlags(getTypeOfSymbol(prop)) & ObjectFlags.ContainsAnyFunctionType) { return undefined; } } @@ -14395,7 +14399,7 @@ namespace ts { // not contain anyFunctionType when we come back to this argument for its second round // of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard // when constructing types from type parameters that had no inference candidates). - if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType || (priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType))) { + if (getObjectFlags(source) & ObjectFlags.ContainsAnyFunctionType || source === silentNeverType || (priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType))) { return; } const inference = getInferenceInfoForType(target); @@ -14698,7 +14702,7 @@ namespace ts { const sourceLen = sourceSignatures.length; const targetLen = targetSignatures.length; const len = sourceLen < targetLen ? sourceLen : targetLen; - const skipParameters = !!(source.flags & TypeFlags.ContainsAnyFunctionType); + const skipParameters = !!(getObjectFlags(source) & ObjectFlags.ContainsAnyFunctionType); for (let i = 0; i < len; i++) { inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getBaseSignature(targetSignatures[targetLen - len + i]), skipParameters); } @@ -15456,7 +15460,7 @@ namespace ts { if (type.flags & TypeFlags.Union) { const types = (type).types; const filtered = filter(types, f); - return filtered === types ? type : getUnionTypeFromSortedList(filtered, (type).primitiveTypesOnly); + return filtered === types ? type : getUnionTypeFromSortedList(filtered, (type).objectFlags); } return f(type) ? type : neverType; } @@ -18362,7 +18366,6 @@ namespace ts { let propertiesTable: SymbolTable; let propertiesArray: Symbol[] = []; let spread: Type = emptyObjectType; - let propagatedFlags: TypeFlags = 0; const contextualType = getApparentTypeOfContextualType(node); const contextualTypeHasPattern = contextualType && contextualType.pattern && @@ -18372,7 +18375,7 @@ namespace ts { const isInJavascript = isInJSFile(node) && !isInJsonFile(node); const enumTag = getJSDocEnumTag(node); const isJSObjectLiteral = !contextualType && isInJavascript && !enumTag; - let typeFlags: TypeFlags = 0; + let objectFlags: ObjectFlags = freshObjectLiteralFlag; let patternWithComputedProperties = false; let hasComputedStringProperty = false; let hasComputedNumberProperty = false; @@ -18400,7 +18403,7 @@ namespace ts { checkTypeAssignableTo(type, getTypeFromTypeNode(enumTag.typeExpression), memberDecl); } } - typeFlags |= type.flags; + objectFlags |= getObjectFlags(type) & ObjectFlags.PropagatingFlags; const nameType = computedNameType && isTypeUsableAsPropertyName(computedNameType) ? computedNameType : undefined; const prop = nameType ? createSymbol(SymbolFlags.Property | member.flags, getPropertyNameFromType(nameType), checkFlags | CheckFlags.Late) : @@ -18448,19 +18451,18 @@ namespace ts { checkExternalEmitHelpers(memberDecl, ExternalEmitHelpers.Assign); } if (propertiesArray.length > 0) { - spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, ObjectFlags.FreshLiteral, inConstContext); + spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext); propertiesArray = []; propertiesTable = createSymbolTable(); hasComputedStringProperty = false; hasComputedNumberProperty = false; - typeFlags = 0; } const type = checkExpression(memberDecl.expression); if (!isValidSpreadType(type)) { error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types); return errorType; } - spread = getSpreadType(spread, type, node.symbol, propagatedFlags, ObjectFlags.FreshLiteral, inConstContext); + spread = getSpreadType(spread, type, node.symbol, objectFlags, inConstContext); offset = i + 1; continue; } @@ -18510,7 +18512,7 @@ namespace ts { if (spread !== emptyObjectType) { if (propertiesArray.length > 0) { - spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, ObjectFlags.FreshLiteral, inConstContext); + spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext); } return spread; } @@ -18521,8 +18523,7 @@ namespace ts { const stringIndexInfo = hasComputedStringProperty ? getObjectLiteralIndexInfo(node, offset, propertiesArray, IndexKind.String) : undefined; const numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node, offset, propertiesArray, IndexKind.Number) : undefined; const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - result.flags |= TypeFlags.ContainsObjectLiteral | typeFlags & TypeFlags.PropagatingFlags; - result.objectFlags |= ObjectFlags.ObjectLiteral | freshObjectLiteralFlag; + result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectLiteral; if (isJSObjectLiteral) { result.objectFlags |= ObjectFlags.JSLiteral; } @@ -18532,7 +18533,6 @@ namespace ts { if (inDestructuringPattern) { result.pattern = node; } - propagatedFlags |= result.flags & TypeFlags.PropagatingFlags; return result; } } @@ -18623,7 +18623,6 @@ namespace ts { let hasSpreadAnyType = false; let typeToIntersect: Type | undefined; let explicitlySpecifyChildrenAttribute = false; - let typeFlags: TypeFlags = 0; let objectFlags: ObjectFlags = ObjectFlags.JsxAttributes; const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement)); @@ -18631,7 +18630,7 @@ namespace ts { const member = attributeDecl.symbol; if (isJsxAttribute(attributeDecl)) { const exprType = checkJsxAttribute(attributeDecl, checkMode); - typeFlags |= exprType.flags & TypeFlags.PropagatingFlags; + objectFlags |= getObjectFlags(exprType) & ObjectFlags.PropagatingFlags; const attributeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.escapedName); attributeSymbol.declarations = member.declarations; @@ -18649,7 +18648,7 @@ namespace ts { else { Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute); if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, typeFlags, objectFlags, /*readonly*/ false); + spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false); attributesTable = createSymbolTable(); } const exprType = checkExpressionCached(attributeDecl.expression, checkMode); @@ -18657,7 +18656,7 @@ namespace ts { hasSpreadAnyType = true; } if (isValidSpreadType(exprType)) { - spread = getSpreadType(spread, exprType, attributes.symbol, typeFlags, objectFlags, /*readonly*/ false); + spread = getSpreadType(spread, exprType, attributes.symbol, objectFlags, /*readonly*/ false); } else { typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType; @@ -18667,7 +18666,7 @@ namespace ts { if (!hasSpreadAnyType) { if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, typeFlags, objectFlags, /*readonly*/ false); + spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false); } } @@ -18699,7 +18698,7 @@ namespace ts { const childPropMap = createSymbolTable(); childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol); spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined), - attributes.symbol, typeFlags, objectFlags, /*readonly*/ false); + attributes.symbol, objectFlags, /*readonly*/ false); } } @@ -18720,8 +18719,7 @@ namespace ts { function createJsxAttributesType() { objectFlags |= freshObjectLiteralFlag; const result = createAnonymousType(attributes.symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); - result.flags |= TypeFlags.ContainsObjectLiteral | typeFlags; - result.objectFlags |= ObjectFlags.ObjectLiteral | objectFlags; + result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectLiteral; return result; } } @@ -21386,7 +21384,7 @@ namespace ts { const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); const defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); anonymousSymbol.type = defaultContainingObject; - synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*typeFLags*/ 0, /*objectFlags*/ 0, /*readonly*/ false) : defaultContainingObject; + synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*objectFlags*/ 0, /*readonly*/ false) : defaultContainingObject; } else { synthType.syntheticType = type; @@ -22064,7 +22062,7 @@ namespace ts { const returnType = getReturnTypeFromBody(node, checkMode); const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, undefined, undefined); - returnOnlyType.flags |= TypeFlags.ContainsAnyFunctionType; + returnOnlyType.objectFlags |= ObjectFlags.ContainsAnyFunctionType; return links.contextFreeType = returnOnlyType; } return anyFunctionType; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a524ce13cb9..c0ae3b99c44 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3817,39 +3817,33 @@ namespace ts { } export const enum TypeFlags { - Any = 1 << 0, - Unknown = 1 << 1, - String = 1 << 2, - Number = 1 << 3, - Boolean = 1 << 4, - Enum = 1 << 5, - BigInt = 1 << 6, - StringLiteral = 1 << 7, - NumberLiteral = 1 << 8, - BooleanLiteral = 1 << 9, - EnumLiteral = 1 << 10, // Always combined with StringLiteral, NumberLiteral, or Union - BigIntLiteral = 1 << 11, - ESSymbol = 1 << 12, // Type of symbol primitive introduced in ES6 - UniqueESSymbol = 1 << 13, // unique symbol - Void = 1 << 14, - Undefined = 1 << 15, - Null = 1 << 16, - Never = 1 << 17, // Never type - TypeParameter = 1 << 18, // Type parameter - Object = 1 << 19, // Object type - Union = 1 << 20, // Union (T | U) - Intersection = 1 << 21, // Intersection (T & U) - Index = 1 << 22, // keyof T - IndexedAccess = 1 << 23, // T[K] - Conditional = 1 << 24, // T extends U ? X : Y - Substitution = 1 << 25, // Type parameter substitution - NonPrimitive = 1 << 26, // intrinsic object type - /* @internal */ - ContainsWideningType = 1 << 27, // Type is or contains undefined or null widening type - /* @internal */ - ContainsObjectLiteral = 1 << 28, // Type is or contains object literal type - /* @internal */ - ContainsAnyFunctionType = 1 << 29, // Type is or contains the anyFunctionType + Any = 1 << 0, + Unknown = 1 << 1, + String = 1 << 2, + Number = 1 << 3, + Boolean = 1 << 4, + Enum = 1 << 5, + BigInt = 1 << 6, + StringLiteral = 1 << 7, + NumberLiteral = 1 << 8, + BooleanLiteral = 1 << 9, + EnumLiteral = 1 << 10, // Always combined with StringLiteral, NumberLiteral, or Union + BigIntLiteral = 1 << 11, + ESSymbol = 1 << 12, // Type of symbol primitive introduced in ES6 + UniqueESSymbol = 1 << 13, // unique symbol + Void = 1 << 14, + Undefined = 1 << 15, + Null = 1 << 16, + Never = 1 << 17, // Never type + TypeParameter = 1 << 18, // Type parameter + Object = 1 << 19, // Object type + Union = 1 << 20, // Union (T | U) + Intersection = 1 << 21, // Intersection (T & U) + Index = 1 << 22, // keyof T + IndexedAccess = 1 << 23, // T[K] + Conditional = 1 << 24, // T extends U ? X : Y + Substitution = 1 << 25, // Type parameter substitution + NonPrimitive = 1 << 26, // intrinsic object type /* @internal */ AnyOrUnknown = Any | Unknown, @@ -3883,29 +3877,29 @@ namespace ts { InstantiablePrimitive = Index, Instantiable = InstantiableNonPrimitive | InstantiablePrimitive, StructuredOrInstantiable = StructuredType | Instantiable, - + /* @internal */ + ObjectFlagsType = Nullable | Object | Union | Intersection, // 'Narrowable' types are types where narrowing actually narrows. // This *should* be every type other than null, undefined, void, and never Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive, NotUnionOrUnit = Any | Unknown | ESSymbol | Object | NonPrimitive, /* @internal */ NotPrimitiveUnion = Any | Unknown | Enum | Void | Never | StructuredOrInstantiable, + // The following flags are aggregated during union and intersection type construction /* @internal */ - RequiresWidening = ContainsWideningType | ContainsObjectLiteral, - /* @internal */ - PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType, + IncludesMask = Any | Unknown | Primitive | Never | Object | Union, // The following flags are used for different purposes during union and intersection type construction /* @internal */ - NonWideningType = ContainsWideningType, + IncludesStructuredOrInstantiable = TypeParameter, /* @internal */ - Wildcard = ContainsObjectLiteral, + IncludesNonWideningType = Intersection, /* @internal */ - EmptyObject = ContainsAnyFunctionType, + IncludesWildcard = Index, /* @internal */ - ConstructionFlags = NonWideningType | Wildcard | EmptyObject, + IncludesEmptyObject = IndexedAccess, // The following flag is used for different purposes by maybeTypeOfKind /* @internal */ - GenericMappedType = ContainsWideningType + GenericMappedType = Never, } export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; @@ -3932,6 +3926,12 @@ namespace ts { // Intrinsic types (TypeFlags.Intrinsic) export interface IntrinsicType extends Type { intrinsicName: string; // Name of intrinsic type + objectFlags: ObjectFlags; + } + + /* @internal */ + export interface NullableType extends IntrinsicType { + objectFlags: ObjectFlags; } /* @internal */ @@ -3991,9 +3991,24 @@ namespace ts { MarkerType = 1 << 13, // Marker type used for variance probing JSLiteral = 1 << 14, // Object type declared in JS - disables errors on read/write of nonexisting members FreshLiteral = 1 << 15, // Fresh object literal - ClassOrInterface = Class | Interface + /* @internal */ + PrimitiveUnion = 1 << 16, // Union of only primitive types + /* @internal */ + ContainsWideningType = 1 << 17, // Type is or contains undefined or null widening type + /* @internal */ + ContainsObjectLiteral = 1 << 18, // Type is or contains object literal type + /* @internal */ + ContainsAnyFunctionType = 1 << 19, // Type is or contains the anyFunctionType + ClassOrInterface = Class | Interface, + /* @internal */ + RequiresWidening = ContainsWideningType | ContainsObjectLiteral, + /* @internal */ + PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType } + /* @internal */ + export type ObjectFlagsType = NullableType | ObjectType | UnionType | IntersectionType; + // Object types (TypeFlags.ObjectType) export interface ObjectType extends Type { objectFlags: ObjectFlags; @@ -4074,6 +4089,8 @@ namespace ts { export interface UnionOrIntersectionType extends Type { types: Type[]; // Constituent types /* @internal */ + objectFlags: ObjectFlags; + /* @internal */ propertyCache: SymbolTable; // Cache of resolved properties /* @internal */ resolvedProperties: Symbol[]; @@ -4088,8 +4105,6 @@ namespace ts { } export interface UnionType extends UnionOrIntersectionType { - /* @internal */ - primitiveTypesOnly: boolean; } export interface IntersectionType extends UnionOrIntersectionType { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 29d2ebfa59e..aa2ebe3d60c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4515,7 +4515,7 @@ namespace ts { } export function getObjectFlags(type: Type): ObjectFlags { - return type.flags & TypeFlags.Object ? (type).objectFlags : 0; + return type.flags & TypeFlags.ObjectFlagsType ? (type).objectFlags : 0; } export function typeHasCallOrConstructSignatures(type: Type, checker: TypeChecker) {