Remove TypeFlags.UnionOfPrimitiveTypes

This commit is contained in:
Anders Hejlsberg
2018-11-05 18:04:57 -08:00
parent 85dbc0438f
commit aa023eb6e3
2 changed files with 27 additions and 20 deletions

View File

@@ -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<Signature>): 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>): Type {
function getUnionTypeFromSortedList(types: Type[], primitiveTypesOnly: boolean, aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray<Type>): 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 = <UnionType>createType(TypeFlags.Union | propagatedFlags | unionOfUnitTypes);
type = <UnionType>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) && (<UnionType>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 && (<UnionType>t).primitiveTypesOnly) {
(unionTypes || (unionTypes = [<UnionType>types[index]])).push(<UnionType>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(<UnionType>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 = (<UnionType>type).types;
const filtered = filter(types, f);
return filtered === types ? type : getUnionTypeFromSortedList(filtered, type.flags & TypeFlags.UnionOfPrimitiveTypes);
return filtered === types ? type : getUnionTypeFromSortedList(filtered, (<UnionType>type).primitiveTypesOnly);
}
return f(type) ? type : neverType;
}

View File

@@ -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 */