From 35be8c351cadbc0fcb63d7370316db7856c31331 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 24 Oct 2016 10:02:04 -0700 Subject: [PATCH] Add more commentary to getSpreadType --- src/compiler/checker.ts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cfe33252d67..2378c65f6c3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5794,23 +5794,29 @@ namespace ts { return spread; } + /** + * Since the source of spread types are object literals and type literals, which are not binary, + * 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, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type { - // TODO: Reorder everything now that it's order independent, to be easier to read const id = getTypeListId([left, right]); if (id in spreadTypes) { return spreadTypes[id]; } - // non-spreadable types + // any spreads to any if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } + // flatten intersections to objects if all member types are objects if (left.flags & TypeFlags.Intersection) { left = resolveObjectIntersection(left as IntersectionType); } if (right.flags & TypeFlags.Intersection) { right = resolveObjectIntersection(right as IntersectionType); } + // distribute unions if (left.flags & TypeFlags.Union) { const spreads = map((left as UnionType).types, t => getSpreadType(t, right, symbol, aliasSymbol, aliasTypeArguments)); @@ -5821,7 +5827,14 @@ namespace ts { t => getSpreadType(left, t, symbol, aliasSymbol, aliasTypeArguments)); return getUnionType(spreads, /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments); } - if (right.flags & TypeFlags.Primitive) { + // skip primitives + if (left.flags & TypeFlags.Primitive && right.flags & TypeFlags.Primitive) { + return emptyObjectType; + } + else if (left.flags & TypeFlags.Primitive) { + return right; + } + else if (right.flags & TypeFlags.Primitive) { return left; } @@ -5845,7 +5858,7 @@ namespace ts { // (T ... U) ... V to T ... (U ... V) const rspread = right as SpreadType; if (rspread.left === emptyObjectType) { - // U ... ({} ... T) => (U ... T) + // ... U ... ({} ... T) => ... U ... T return getSpreadType(left, rspread.right, symbol, aliasSymbol, aliasTypeArguments); } return getSpreadType(getSpreadType(left, rspread.left, symbol, aliasSymbol, aliasTypeArguments),