Proper handling of top type in intersection types

This commit is contained in:
Anders Hejlsberg 2018-05-25 09:03:30 -07:00
parent 4c417833a9
commit 0d9dc89a78
2 changed files with 25 additions and 12 deletions

View file

@ -447,6 +447,7 @@ namespace ts {
let deferredGlobalTemplateStringsArrayType: ObjectType;
let deferredGlobalImportMetaType: ObjectType;
let deferredGlobalExtractSymbol: Symbol;
let deferredTopType: Type;
let deferredNodes: Node[] | undefined;
const allPotentiallyUnusedIdentifiers = createMap<PotentiallyUnusedIdentifier[]>(); // key is file name
@ -8510,14 +8511,21 @@ namespace ts {
return links.resolvedType;
}
function getTopType() {
return deferredTopType || (deferredTopType = getUnionType([emptyObjectType, nullType, undefinedType]));
}
function addTypeToIntersection(typeSet: Type[], includes: TypeFlags, type: Type) {
const flags = type.flags;
if (flags & TypeFlags.Intersection) {
return addTypesToIntersection(typeSet, includes, (<IntersectionType>type).types);
}
if (getObjectFlags(type) & ObjectFlags.EmptyObjectType) {
if (getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type)) {
includes |= TypeFlags.EmptyObject;
}
else if (type.flags & TypeFlags.Union && type === getTopType()) {
includes |= TypeFlags.TopUnion;
}
else {
includes |= flags & ~TypeFlags.ConstructionFlags;
if (flags & TypeFlags.Any) {
@ -8591,9 +8599,6 @@ namespace ts {
// Also, unlike union types, the order of the constituent types is preserved in order that overload resolution
// for intersections of types with signatures can be deterministic.
function getIntersectionType(types: Type[], aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
if (types.length === 0) {
return emptyObjectType;
}
const typeSet: Type[] = [];
const includes = addTypesToIntersection(typeSet, 0, types);
if (includes & TypeFlags.Never) {
@ -8602,12 +8607,18 @@ namespace ts {
if (includes & TypeFlags.Any) {
return includes & TypeFlags.Wildcard ? wildcardType : anyType;
}
if (!strictNullChecks && includes & TypeFlags.Nullable) {
return includes & TypeFlags.Undefined ? undefinedType : nullType;
}
if (types.length === 0) {
return includes & TypeFlags.TopUnion ? getTopType() : emptyObjectType;
}
if (includes & TypeFlags.String && includes & TypeFlags.StringLiteral ||
includes & TypeFlags.Number && includes & TypeFlags.NumberLiteral ||
includes & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol) {
removeRedundantPrimitiveTypes(typeSet, includes);
}
if (includes & TypeFlags.EmptyObject && !(includes & TypeFlags.Object)) {
if (includes & TypeFlags.EmptyObject && !(includes & TypeFlags.Object) && includes & TypeFlags.Nullable) {
typeSet.push(emptyObjectType);
}
if (typeSet.length === 1) {

View file

@ -3687,17 +3687,17 @@ namespace ts {
IndexedAccess = 1 << 20, // T[K]
Conditional = 1 << 21, // T extends U ? X : Y
Substitution = 1 << 22, // Type parameter substitution
NonPrimitive = 1 << 23, // intrinsic object type
/* @internal */
FreshLiteral = 1 << 23, // Fresh literal or unique type
FreshLiteral = 1 << 24, // Fresh literal or unique type
/* @internal */
ContainsWideningType = 1 << 24, // Type is or contains undefined or null widening type
UnionOfUnitTypes = 1 << 25, // Type is union of unit types
/* @internal */
ContainsObjectLiteral = 1 << 25, // Type is or contains object literal type
ContainsWideningType = 1 << 26, // Type is or contains undefined or null widening type
/* @internal */
ContainsAnyFunctionType = 1 << 26, // Type is or contains the anyFunctionType
NonPrimitive = 1 << 27, // intrinsic object type
ContainsObjectLiteral = 1 << 27, // Type is or contains object literal type
/* @internal */
UnionOfUnitTypes = 1 << 28, // Type is union of unit types
ContainsAnyFunctionType = 1 << 28, // Type is or contains the anyFunctionType
/* @internal */
GenericMappedType = 1 << 29, // Flag used by maybeTypeOfKind
@ -3749,7 +3749,9 @@ namespace ts {
/* @internal */
EmptyObject = ContainsAnyFunctionType,
/* @internal */
ConstructionFlags = NonWideningType | Wildcard | EmptyObject
TopUnion = GenericMappedType,
/* @internal */
ConstructionFlags = NonWideningType | Wildcard | EmptyObject | GenericMappedType
}
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;