From aa023eb6e32205d4c43b89ee425c4b411ca0e0c1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 5 Nov 2018 18:04:57 -0800 Subject: [PATCH 1/5] Remove TypeFlags.UnionOfPrimitiveTypes --- src/compiler/checker.ts | 34 ++++++++++++++++++++-------------- src/compiler/types.ts | 13 +++++++------ 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5c187d6ad8af9..4bd2dd54908b1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9012,7 +9012,7 @@ namespace ts { neverType; } } - return getUnionTypeFromSortedList(typeSet, includes & TypeFlags.NotPrimitiveUnion ? 0 : TypeFlags.UnionOfPrimitiveTypes, aliasSymbol, aliasTypeArguments); + return getUnionTypeFromSortedList(typeSet, !(includes & TypeFlags.NotPrimitiveUnion), aliasSymbol, aliasTypeArguments); } function getUnionTypePredicate(signatures: ReadonlyArray): TypePredicate | undefined { @@ -9052,7 +9052,7 @@ namespace ts { } // This function assumes the constituent type list is sorted and deduplicated. - function getUnionTypeFromSortedList(types: Type[], unionOfUnitTypes: TypeFlags, aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray): Type { + function getUnionTypeFromSortedList(types: Type[], primitiveTypesOnly: boolean, aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray): Type { if (types.length === 0) { return neverType; } @@ -9063,9 +9063,10 @@ namespace ts { let type = unionTypes.get(id); if (!type) { const propagatedFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable); - type = createType(TypeFlags.Union | propagatedFlags | unionOfUnitTypes); + type = createType(TypeFlags.Union | propagatedFlags); unionTypes.set(id, type); 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. @@ -9157,13 +9158,16 @@ 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.UnionOfPrimitiveTypes) !== 0); + const index = findIndex(types, t => !!(t.flags & TypeFlags.Union) && (t).primitiveTypesOnly); + if (index < 0) { + return false; + } let i = index + 1; // Remove all but the first union of primitive types and collect them in // the unionTypes array. while (i < types.length) { const t = types[i]; - if (t.flags & TypeFlags.UnionOfPrimitiveTypes) { + if (t.flags & TypeFlags.Union && (t).primitiveTypesOnly) { (unionTypes || (unionTypes = [types[index]])).push(t); orderedRemoveItemAt(types, i); } @@ -9190,7 +9194,7 @@ namespace ts { } } // Finally replace the first union with the result - types[index] = getUnionTypeFromSortedList(result, TypeFlags.UnionOfPrimitiveTypes); + types[index] = getUnionTypeFromSortedList(result, /*primitiveTypesOnly*/ true); return true; } @@ -9232,7 +9236,7 @@ namespace ts { return typeSet[0]; } if (includes & TypeFlags.Union) { - if (includes & TypeFlags.UnionOfPrimitiveTypes && intersectUnionsOfPrimitiveTypes(typeSet)) { + if (intersectUnionsOfPrimitiveTypes(typeSet)) { // When the intersection creates a reduced set (which might mean that *all* union types have // disappeared), we restart the operation to get a new set of combined flags. Once we have // reduced we'll never reduce again, so this occurs at most once. @@ -11809,12 +11813,14 @@ namespace ts { } // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly - function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) { - const sourceProperties = getPropertiesOfObjectType(source); - if (sourceProperties) { - const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); - if (sourcePropertiesFiltered) { - return discriminateTypeByDiscriminableItems(target, map(sourcePropertiesFiltered, p => ([() => getTypeOfSymbol(p), p.escapedName] as [() => Type, __String])), isRelatedTo); + function findMatchingDiscriminantType(source: Type, target: Type) { + if (target.flags & TypeFlags.Union) { + const sourceProperties = getPropertiesOfObjectType(source); + if (sourceProperties) { + const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); + if (sourcePropertiesFiltered) { + return discriminateTypeByDiscriminableItems(target, map(sourcePropertiesFiltered, p => ([() => getTypeOfSymbol(p), p.escapedName] as [() => Type, __String])), isRelatedTo); + } } } return undefined; @@ -14846,7 +14852,7 @@ namespace ts { if (type.flags & TypeFlags.Union) { const types = (type).types; const filtered = filter(types, f); - return filtered === types ? type : getUnionTypeFromSortedList(filtered, type.flags & TypeFlags.UnionOfPrimitiveTypes); + return filtered === types ? type : getUnionTypeFromSortedList(filtered, (type).primitiveTypesOnly); } return f(type) ? type : neverType; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 46a5ed91275ed..0ca4de3f53753 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3838,13 +3838,11 @@ namespace ts { /* @internal */ FreshLiteral = 1 << 27, // Fresh literal or unique type /* @internal */ - UnionOfPrimitiveTypes = 1 << 28, // Type is union of primitive types + ContainsWideningType = 1 << 28, // Type is or contains undefined or null widening type /* @internal */ - ContainsWideningType = 1 << 29, // Type is or contains undefined or null widening type + ContainsObjectLiteral = 1 << 29, // Type is or contains object literal type /* @internal */ - ContainsObjectLiteral = 1 << 30, // Type is or contains object literal type - /* @internal */ - ContainsAnyFunctionType = 1 << 31, // Type is or contains the anyFunctionType + ContainsAnyFunctionType = 1 << 30, // Type is or contains the anyFunctionType /* @internal */ AnyOrUnknown = Any | Unknown, @@ -4077,7 +4075,10 @@ namespace ts { couldContainTypeVariables: boolean; } - export interface UnionType extends UnionOrIntersectionType { } + export interface UnionType extends UnionOrIntersectionType { + /* @internal */ + primitiveTypesOnly: boolean; + } export interface IntersectionType extends UnionOrIntersectionType { /* @internal */ From 76a742191f79456f8ff8cb214a2eadd9b8676506 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 6 Nov 2018 06:25:10 -0800 Subject: [PATCH 2/5] Remove usage of TypeFlags.FreshLiteral for fresh literal types --- src/compiler/checker.ts | 45 ++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4bd2dd54908b1..589239bce516b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -408,11 +408,13 @@ namespace ts { const regularFalseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false") as FreshableIntrinsicType; const trueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true") as FreshableIntrinsicType; const regularTrueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true") as FreshableIntrinsicType; - falseType.flags |= TypeFlags.FreshLiteral; - trueType.flags |= TypeFlags.FreshLiteral; trueType.regularType = regularTrueType; + trueType.freshType = trueType; + regularTrueType.regularType = regularTrueType; regularTrueType.freshType = trueType; falseType.regularType = regularFalseType; + falseType.freshType = falseType; + regularFalseType.regularType = regularFalseType; regularFalseType.freshType = falseType; const booleanType = createBooleanType([regularFalseType, regularTrueType]); // Also mark all combinations of fresh/regular booleans as "Boolean" so they print as `boolean` instead of `true | false` @@ -8969,7 +8971,7 @@ namespace ts { t.flags & TypeFlags.NumberLiteral && includes & TypeFlags.Number || t.flags & TypeFlags.BigIntLiteral && includes & TypeFlags.BigInt || t.flags & TypeFlags.UniqueESSymbol && includes & TypeFlags.ESSymbol || - t.flags & TypeFlags.Literal && t.flags & TypeFlags.FreshLiteral && containsType(types, (t).regularType); + isFreshLiteralType(t) && containsType(types, (t).regularType); if (remove) { orderedRemoveItemAt(types, i); } @@ -10039,10 +10041,11 @@ namespace ts { } function getFreshTypeOfLiteralType(type: Type): Type { - if (type.flags & TypeFlags.Literal && !(type.flags & TypeFlags.FreshLiteral)) { - if (!(type).freshType) { // NOTE: Safe because all freshable intrinsics always have fresh types already - const freshType = createLiteralType(type.flags | TypeFlags.FreshLiteral, (type).value, (type).symbol); + if (type.flags & TypeFlags.Literal) { + if (!(type).freshType) { + const freshType = createLiteralType(type.flags, (type).value, (type).symbol); freshType.regularType = type; + freshType.freshType = freshType; (type).freshType = freshType; } return (type).freshType; @@ -10051,11 +10054,15 @@ namespace ts { } function getRegularTypeOfLiteralType(type: Type): Type { - return type.flags & TypeFlags.Literal && type.flags & TypeFlags.FreshLiteral ? (type).regularType : + return type.flags & TypeFlags.Literal ? (type).regularType : type.flags & TypeFlags.Union ? getUnionType(sameMap((type).types, getRegularTypeOfLiteralType)) : type; } + function isFreshLiteralType(type: Type) { + return !!(type.flags & TypeFlags.Literal) && (type).freshType === type; + } + function getLiteralType(value: string | number | PseudoBigInt, enumId?: number, symbol?: Symbol) { // We store all literal types in a single map with keys of the form '#NNN' and '@SSS', // where NNN is the text representation of a numeric literal and SSS are the characters @@ -10069,6 +10076,7 @@ namespace ts { typeof value === "string" ? TypeFlags.StringLiteral : TypeFlags.BigIntLiteral) | (enumId ? TypeFlags.EnumLiteral : 0); literalTypes.set(key, type = createLiteralType(flags, value, symbol)); + type.regularType = type; } return type; } @@ -11340,10 +11348,10 @@ namespace ts { } function isTypeRelatedTo(source: Type, target: Type, relation: Map) { - if (source.flags & TypeFlags.Literal && source.flags & TypeFlags.FreshLiteral) { + if (isFreshLiteralType(source)) { source = (source).regularType; } - if (target.flags & TypeFlags.Literal && target.flags & TypeFlags.FreshLiteral) { + if (isFreshLiteralType(target)) { target = (target).regularType; } if (source === target || @@ -11498,10 +11506,10 @@ namespace ts { * * Ternary.False if they are not related. */ function isRelatedTo(source: Type, target: Type, reportErrors = false, headMessage?: DiagnosticMessage, isApparentIntersectionConstituent?: boolean): Ternary { - if (source.flags & TypeFlags.Literal && source.flags & TypeFlags.FreshLiteral) { + if (isFreshLiteralType(source)) { source = (source).regularType; } - if (target.flags & TypeFlags.Literal && target.flags & TypeFlags.FreshLiteral) { + if (isFreshLiteralType(target)) { target = (target).regularType; } if (source.flags & TypeFlags.Substitution) { @@ -13113,11 +13121,11 @@ namespace ts { } function getWidenedLiteralType(type: Type): Type { - return type.flags & TypeFlags.EnumLiteral && type.flags & TypeFlags.FreshLiteral ? getBaseTypeOfEnumLiteralType(type) : - type.flags & TypeFlags.StringLiteral && type.flags & TypeFlags.FreshLiteral ? stringType : - type.flags & TypeFlags.NumberLiteral && type.flags & TypeFlags.FreshLiteral ? numberType : - type.flags & TypeFlags.BigIntLiteral && type.flags & TypeFlags.FreshLiteral ? bigintType : - type.flags & TypeFlags.BooleanLiteral && type.flags & TypeFlags.FreshLiteral ? booleanType : + return type.flags & TypeFlags.EnumLiteral && isFreshLiteralType(type) ? getBaseTypeOfEnumLiteralType(type) : + type.flags & TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType : + type.flags & TypeFlags.NumberLiteral && isFreshLiteralType(type) ? numberType : + type.flags & TypeFlags.BigIntLiteral && isFreshLiteralType(type) ? bigintType : + type.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(type) ? booleanType : type.flags & TypeFlags.Union ? getUnionType(sameMap((type).types, getWidenedLiteralType)) : type; } @@ -14530,7 +14538,7 @@ namespace ts { return assignedType; } let reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t)); - if (assignedType.flags & TypeFlags.FreshLiteral && assignedType.flags & TypeFlags.BooleanLiteral) { + if (assignedType.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(assignedType)) { reducedType = mapType(reducedType, getFreshTypeOfLiteralType); // Ensure that if the assignment is a fresh type, that we narrow to fresh types } // Our crude heuristic produces an invalid result in some cases: see GH#26130. @@ -28768,8 +28776,7 @@ namespace ts { function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean { if (isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConst(node)) { - const type = getTypeOfSymbol(getSymbolOfNode(node)); - return !!(type.flags & TypeFlags.Literal && type.flags & TypeFlags.FreshLiteral); + return isFreshLiteralType(getTypeOfSymbol(getSymbolOfNode(node))); } return false; } From 7df5a2cf8c4d7363e9afce5d5a1a74b9865d329d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 6 Nov 2018 13:31:56 -0800 Subject: [PATCH 3/5] Remove pointless check --- src/compiler/checker.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 589239bce516b..c3653c771da37 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17807,9 +17807,7 @@ namespace ts { if (inDestructuringPattern) { result.pattern = node; } - if (!(result.flags & TypeFlags.Nullable)) { - propagatedFlags |= (result.flags & TypeFlags.PropagatingFlags); - } + propagatedFlags |= (result.flags & TypeFlags.PropagatingFlags); return result; } } From e63ffe54fdecab18ee6cec306f14d7114385a7e2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 6 Nov 2018 15:00:34 -0800 Subject: [PATCH 4/5] Move FreshLiteral flag from TypeFlags to ObjectFlags --- src/compiler/checker.ts | 45 +++++++++++++++++++++-------------------- src/compiler/types.ts | 9 ++++----- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c3653c771da37..873688dfd8ab3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -82,6 +82,7 @@ namespace ts { const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny"); const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis"); const keyofStringsOnly = !!compilerOptions.keyofStringsOnly; + const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ObjectFlags.FreshLiteral; const emitResolver = createResolver(); const nodeBuilder = createNodeBuilder(); @@ -10000,8 +10001,8 @@ namespace ts { emptyArray, getNonReadonlyIndexSignature(stringIndexInfo), getNonReadonlyIndexSignature(numberIndexInfo)); - spread.flags |= typeFlags | TypeFlags.ContainsObjectLiteral; - (spread as ObjectType).objectFlags |= objectFlags | (ObjectFlags.ObjectLiteral | ObjectFlags.ContainsSpread); + spread.flags |= TypeFlags.ContainsObjectLiteral | typeFlags; + spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsSpread | objectFlags; return spread; } @@ -11553,7 +11554,7 @@ namespace ts { isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True; const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes); - if (isObjectLiteralType(source) && source.flags & TypeFlags.FreshLiteral) { + if (isObjectLiteralType(source) && getObjectFlags(source) & ObjectFlags.FreshLiteral) { const discriminantType = target.flags & TypeFlags.Union ? findMatchingDiscriminantType(source, target as UnionType) : undefined; if (hasExcessProperties(source, target, discriminantType, reportErrors)) { if (reportErrors) { @@ -13284,7 +13285,7 @@ namespace ts { * Leave signatures alone since they are not subject to the check. */ function getRegularTypeOfObjectLiteral(type: Type): Type { - if (!(isObjectLiteralType(type) && type.flags & TypeFlags.FreshLiteral)) { + if (!(isObjectLiteralType(type) && getObjectFlags(type) & ObjectFlags.FreshLiteral)) { return type; } const regularType = (type).regularType; @@ -13300,7 +13301,7 @@ namespace ts { resolved.constructSignatures, resolved.stringIndexInfo, resolved.numberIndexInfo); - regularNew.flags = resolved.flags & ~TypeFlags.FreshLiteral; + regularNew.flags = resolved.flags; regularNew.objectFlags |= ObjectFlags.ObjectLiteral | (getObjectFlags(resolved) & ObjectFlags.JSLiteral); (type).regularType = regularNew; return regularNew; @@ -17637,7 +17638,7 @@ namespace ts { let propertiesTable: SymbolTable; let propertiesArray: Symbol[] = []; let spread: Type = emptyObjectType; - let propagatedFlags: TypeFlags = TypeFlags.FreshLiteral; + let propagatedFlags: TypeFlags = 0; const contextualType = getApparentTypeOfContextualType(node); const contextualTypeHasPattern = contextualType && contextualType.pattern && @@ -17722,7 +17723,7 @@ namespace ts { checkExternalEmitHelpers(memberDecl, ExternalEmitHelpers.Assign); } if (propertiesArray.length > 0) { - spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, /*objectFlags*/ 0); + spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, ObjectFlags.FreshLiteral); propertiesArray = []; propertiesTable = createSymbolTable(); hasComputedStringProperty = false; @@ -17734,7 +17735,7 @@ namespace ts { error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types); return errorType; } - spread = getSpreadType(spread, type, node.symbol, propagatedFlags, /*objectFlags*/ 0); + spread = getSpreadType(spread, type, node.symbol, propagatedFlags, ObjectFlags.FreshLiteral); offset = i + 1; continue; } @@ -17784,7 +17785,7 @@ namespace ts { if (spread !== emptyObjectType) { if (propertiesArray.length > 0) { - spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, /*objectFlags*/ 0); + spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, ObjectFlags.FreshLiteral); } return spread; } @@ -17795,9 +17796,8 @@ namespace ts { const stringIndexInfo = hasComputedStringProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, IndexKind.String) : undefined; const numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, IndexKind.Number) : undefined; const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral; - result.flags |= TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags); - result.objectFlags |= ObjectFlags.ObjectLiteral; + result.flags |= TypeFlags.ContainsObjectLiteral | typeFlags & TypeFlags.PropagatingFlags; + result.objectFlags |= ObjectFlags.ObjectLiteral | freshObjectLiteralFlag; if (isJSObjectLiteral) { result.objectFlags |= ObjectFlags.JSLiteral; } @@ -17807,7 +17807,7 @@ namespace ts { if (inDestructuringPattern) { result.pattern = node; } - propagatedFlags |= (result.flags & TypeFlags.PropagatingFlags); + propagatedFlags |= result.flags & TypeFlags.PropagatingFlags; return result; } } @@ -17898,14 +17898,15 @@ namespace ts { let hasSpreadAnyType = false; let typeToIntersect: Type | undefined; let explicitlySpecifyChildrenAttribute = false; - let propagatingFlags: TypeFlags = 0; + let typeFlags: TypeFlags = 0; + let objectFlags: ObjectFlags = ObjectFlags.JsxAttributes; const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement)); for (const attributeDecl of attributes.properties) { const member = attributeDecl.symbol; if (isJsxAttribute(attributeDecl)) { const exprType = checkJsxAttribute(attributeDecl, checkMode); - propagatingFlags |= (exprType.flags & TypeFlags.PropagatingFlags); + typeFlags |= exprType.flags & TypeFlags.PropagatingFlags; const attributeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.escapedName); attributeSymbol.declarations = member.declarations; @@ -17923,7 +17924,7 @@ namespace ts { else { Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute); if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, propagatingFlags, ObjectFlags.JsxAttributes); + spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, typeFlags, objectFlags); attributesTable = createSymbolTable(); } const exprType = checkExpressionCached(attributeDecl.expression, checkMode); @@ -17931,7 +17932,7 @@ namespace ts { hasSpreadAnyType = true; } if (isValidSpreadType(exprType)) { - spread = getSpreadType(spread, exprType, attributes.symbol, propagatingFlags, ObjectFlags.JsxAttributes); + spread = getSpreadType(spread, exprType, attributes.symbol, typeFlags, objectFlags); } else { typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType; @@ -17941,7 +17942,7 @@ namespace ts { if (!hasSpreadAnyType) { if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, propagatingFlags, ObjectFlags.JsxAttributes); + spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, typeFlags, objectFlags); } } @@ -17969,7 +17970,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, propagatingFlags, ObjectFlags.JsxAttributes); + attributes.symbol, typeFlags, objectFlags); } } @@ -17988,10 +17989,10 @@ namespace ts { * @param attributesTable a symbol table of attributes property */ function createJsxAttributesType() { + objectFlags |= freshObjectLiteralFlag; const result = createAnonymousType(attributes.symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); - const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral; - result.flags |= (propagatingFlags |= TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag); - result.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.JsxAttributes; + result.flags |= TypeFlags.ContainsObjectLiteral | typeFlags; + result.objectFlags |= ObjectFlags.ObjectLiteral | objectFlags; return result; } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0ca4de3f53753..eed58335363c0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3836,13 +3836,11 @@ namespace ts { Substitution = 1 << 25, // Type parameter substitution NonPrimitive = 1 << 26, // intrinsic object type /* @internal */ - FreshLiteral = 1 << 27, // Fresh literal or unique type + ContainsWideningType = 1 << 27, // Type is or contains undefined or null widening type /* @internal */ - ContainsWideningType = 1 << 28, // Type is or contains undefined or null widening type + ContainsObjectLiteral = 1 << 28, // Type is or contains object literal type /* @internal */ - ContainsObjectLiteral = 1 << 29, // Type is or contains object literal type - /* @internal */ - ContainsAnyFunctionType = 1 << 30, // Type is or contains the anyFunctionType + ContainsAnyFunctionType = 1 << 29, // Type is or contains the anyFunctionType /* @internal */ AnyOrUnknown = Any | Unknown, @@ -3980,6 +3978,7 @@ namespace ts { JsxAttributes = 1 << 12, // Jsx attributes type 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 } From 7e3fd4626a1e25bf81bb364ed5d89d7cd80adcce Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 6 Nov 2018 15:07:00 -0800 Subject: [PATCH 5/5] Accept API baseline changes --- tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index a6b826326cfdb..f3423c96dc346 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2254,6 +2254,7 @@ declare namespace ts { JsxAttributes = 4096, MarkerType = 8192, JSLiteral = 16384, + FreshLiteral = 32768, ClassOrInterface = 3 } interface ObjectType extends Type { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index ec80d7722e26a..8c0f589032a57 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2254,6 +2254,7 @@ declare namespace ts { JsxAttributes = 4096, MarkerType = 8192, JSLiteral = 16384, + FreshLiteral = 32768, ClassOrInterface = 3 } interface ObjectType extends Type {