From 334820c357c50f9926ea4c4cbd09f9673755cf65 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 2 Nov 2016 16:26:34 -0700 Subject: [PATCH 1/4] Remove spread types, leaving spread syntax/emit Spreads are still typed, but cannot be created from a non-object type. Tests still need to be updated. --- src/compiler/checker.ts | 351 ++++----------------------- src/compiler/declarationEmitter.ts | 9 - src/compiler/diagnosticMessages.json | 6 +- src/compiler/parser.ts | 17 -- src/compiler/types.ts | 22 +- src/lib/es2015.core.d.ts | 6 +- 6 files changed, 57 insertions(+), 354 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5447e652f08..c6924e2cb0a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -113,7 +113,6 @@ namespace ts { const tupleTypes: GenericType[] = []; const unionTypes = createMap(); const intersectionTypes = createMap(); - const spreadTypes = createMap(); const stringLiteralTypes = createMap(); const numericLiteralTypes = createMap(); const evolvingArrayTypes: EvolvingArrayType[] = []; @@ -2244,9 +2243,6 @@ namespace ts { else if (type.flags & TypeFlags.UnionOrIntersection) { writeUnionOrIntersectionType(type, nextFlags); } - else if (type.flags & TypeFlags.Spread) { - writeSpreadType(type); - } else if (getObjectFlags(type) & ObjectFlags.Anonymous) { writeAnonymousType(type, nextFlags); } @@ -2362,48 +2358,6 @@ namespace ts { } } - function writeSpreadType(type: SpreadType) { - writePunctuation(writer, SyntaxKind.OpenBraceToken); - writer.writeLine(); - writer.increaseIndent(); - - writeSpreadTypeWorker(type, /*atEnd*/true, type.symbol); - - writer.decreaseIndent(); - writePunctuation(writer, SyntaxKind.CloseBraceToken); - } - - function writeSpreadTypeWorker(type: SpreadType, atEnd: boolean, container: Symbol): void { - if (type.left.flags & TypeFlags.Spread) { - writeSpreadTypeWorker(type.left as SpreadType, /*atEnd*/false, container); - } - else { - const saveInObjectTypeLiteral = inObjectTypeLiteral; - inObjectTypeLiteral = true; - writeObjectLiteralType(resolveStructuredTypeMembers(type.left as ResolvedType)); - inObjectTypeLiteral = saveInObjectTypeLiteral; - } - if (type.right.symbol === container) { - // if type.right was written as part of the spread type, don't surround with ...{ }. - // this gives { a: number, ... T } instead of { ...{ a: number }, ...T } - const saveInObjectTypeLiteral = inObjectTypeLiteral; - inObjectTypeLiteral = true; - writeObjectLiteralType(resolveStructuredTypeMembers(type.right as ResolvedType)); - inObjectTypeLiteral = saveInObjectTypeLiteral; - } - else { - writePunctuation(writer, SyntaxKind.DotDotDotToken); - writeType(type.right, TypeFormatFlags.None); - if (atEnd) { - writeSpace(writer); - } - else { - writePunctuation(writer, SyntaxKind.SemicolonToken); - writer.writeLine(); - } - } - } - function writeAnonymousType(type: ObjectType, flags: TypeFormatFlags) { const symbol = type.symbol; if (symbol) { @@ -3623,7 +3577,6 @@ namespace ts { links.type = getUnionType([getTypeOfSymbol(links.leftSpread), getTypeOfSymbol(links.rightSpread)]); } return links.type; - } function getTargetType(type: Type): Type { @@ -4567,10 +4520,6 @@ namespace ts { return type.resolvedApparentType; } - function getApparentTypeOfSpread(type: SpreadType) { - return getApparentType(type.right); - } - /** * For a type parameter, return the base constraint of the type parameter. For the string, number, * boolean, and symbol primitive types, return the corresponding object types. Otherwise return the @@ -4578,7 +4527,6 @@ namespace ts { */ function getApparentType(type: Type): Type { let t = type.flags & TypeFlags.TypeParameter ? getApparentTypeOfTypeParameter(type) : type; - t = t.flags & TypeFlags.Spread ? getApparentTypeOfSpread(type as SpreadType) : t; return t.flags & TypeFlags.StringLike ? globalStringType : t.flags & TypeFlags.NumberLike ? globalNumberType : t.flags & TypeFlags.BooleanLike ? globalBooleanType : @@ -4640,7 +4588,7 @@ namespace ts { propTypes.push(type); } const result = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | commonFlags, name); - result.syntheticKind === SyntheticSymbolKind.UnionOrIntersection; + result.syntheticKind = SyntheticSymbolKind.UnionOrIntersection; result.containingType = containingType; result.hasNonUniformType = hasNonUniformType; result.isPartial = isPartial; @@ -5917,12 +5865,6 @@ namespace ts { function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - const hasSpread = (node.kind === SyntaxKind.TypeLiteral && - find((node as TypeLiteralNode).members, elt => elt.kind === SyntaxKind.SpreadTypeElement)); - if (hasSpread) { - return getTypeFromSpreadTypeLiteral(node, aliasSymbol, aliasTypeArguments); - } - // Deferred resolution of members is handled by resolveObjectTypeMembers if (isEmpty(node.symbol.members) && !aliasSymbol && !aliasTypeArguments) { links.resolvedType = emptyTypeLiteralType; @@ -5937,187 +5879,56 @@ namespace ts { return links.resolvedType; } - function getTypeFromSpreadTypeLiteral(node: Node, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type { - let spread: Type = emptyObjectType; - let members: Map; - let stringIndexInfo: IndexInfo; - let numberIndexInfo: IndexInfo; - for (const member of (node as TypeLiteralNode).members) { - if (member.kind === SyntaxKind.SpreadTypeElement) { - if (members) { - const type = createAnonymousType(node.symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - spread = getSpreadType(spread, type, node.symbol, aliasSymbol, aliasTypeArguments); - members = undefined; - stringIndexInfo = undefined; - numberIndexInfo = undefined; - } - const type = getTypeFromTypeNode((member as SpreadTypeElement).type); - spread = getSpreadType(spread, type, node.symbol, aliasSymbol, aliasTypeArguments); - } - else if (member.kind !== SyntaxKind.IndexSignature && - member.kind !== SyntaxKind.CallSignature && - member.kind !== SyntaxKind.ConstructSignature) { - // it is an error for spread types to include index, call or construct signatures - const flags = SymbolFlags.Property | SymbolFlags.Transient | (member.questionToken ? SymbolFlags.Optional : 0); - const text = getTextOfPropertyName(member.name); - const symbol = createSymbol(flags, text); - symbol.declarations = [member]; - symbol.valueDeclaration = member; - symbol.type = getTypeFromTypeNodeNoAlias((member as IndexSignatureDeclaration | PropertySignature | MethodSignature).type); - if (!members) { - members = createMap(); - } - members[symbol.name] = symbol; - } - } - if (members || stringIndexInfo || numberIndexInfo) { - const type = createAnonymousType(node.symbol, members || emptySymbols, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - spread = getSpreadType(spread, type, node.symbol, aliasSymbol, aliasTypeArguments); - } - 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 { - const id = getTypeListId([left, right]); - if (id in spreadTypes) { - return spreadTypes[id]; - } - - // 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)); - return getUnionType(spreads, /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments); - } - if (right.flags & TypeFlags.Union) { - const spreads = map((right as UnionType).types, - t => getSpreadType(left, t, symbol, aliasSymbol, aliasTypeArguments)); - return getUnionType(spreads, /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments); - } - // 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; - } - - // spread simplifications - if (left.flags & TypeFlags.Spread && - right.flags & TypeFlags.TypeParameter && - (left as SpreadType).right.flags & TypeFlags.TypeParameter && - right.symbol === (left as SpreadType).right.symbol) { - // for types like T ... T, just return ... T - return left; - } - if (left.flags & TypeFlags.Spread && - right.flags & TypeFlags.Object && - (left as SpreadType).right.flags & TypeFlags.Object) { - // simplify two adjacent object types: T ... { x } ... { y } becomes T ... { x, y } - const simplified = getSpreadType(right, (left as SpreadType).right, symbol, aliasSymbol, aliasTypeArguments); - return getSpreadType((left as SpreadType).left, simplified, symbol, aliasSymbol, aliasTypeArguments); - } - if (right.flags & TypeFlags.Spread) { - // spread is right associative and associativity applies, so transform - // (T ... U) ... V to T ... (U ... V) - const rspread = right as SpreadType; - if (rspread.left === emptyObjectType) { - // ... U ... ({} ... T) => ... U ... T - return getSpreadType(left, rspread.right, symbol, aliasSymbol, aliasTypeArguments); - } - return getSpreadType(getSpreadType(left, rspread.left, symbol, aliasSymbol, aliasTypeArguments), - rspread.right, symbol, aliasSymbol, aliasTypeArguments); - } - - // create an object type if left and right are both objects, - // otherwise create a spread type - if (right.flags & TypeFlags.Object && left.flags & TypeFlags.Object) { - const members = createMap(); - const skippedPrivateMembers = createMap(); - const stringIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.String), getIndexInfoOfType(right, IndexKind.String)); - const numberIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.Number), getIndexInfoOfType(right, IndexKind.Number)); - - const isFromSpread = right.symbol !== symbol; - for (const rightProp of getPropertiesOfType(right)) { - if (getDeclarationModifierFlagsFromSymbol(rightProp) & (ModifierFlags.Private | ModifierFlags.Protected)) { - skippedPrivateMembers[rightProp.name] = true; - } - else if (!(rightProp.flags & SymbolFlags.Method && isFromSpread) && - !(rightProp.flags & SymbolFlags.SetAccessor && !(rightProp.flags & SymbolFlags.GetAccessor))) { - // skip methods from spreads and accessors with setters but no getters - members[rightProp.name] = rightProp; - } - } - for (const leftProp of getPropertiesOfType(left)) { - if (leftProp.flags & SymbolFlags.SetAccessor && !(leftProp.flags & SymbolFlags.GetAccessor) - || leftProp.name in skippedPrivateMembers) { - continue; - } - if (leftProp.name in members) { - const rightProp = members[leftProp.name]; - if (rightProp.flags & SymbolFlags.Optional) { - const declarations: Declaration[] = concatenate(leftProp.declarations, rightProp.declarations); - const flags = SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | (leftProp.flags & SymbolFlags.Optional); - const result = createSymbol(flags, leftProp.name); - result.syntheticKind = SyntheticSymbolKind.Spread; - result.leftSpread = leftProp; - result.rightSpread = rightProp; - result.declarations = declarations; - if (declarations.length) { - result.valueDeclaration = declarations[0]; - } - result.isReadonly = isReadonlySymbol(leftProp) || isReadonlySymbol(rightProp); - members[leftProp.name] = result; - } - } - else { - members[leftProp.name] = leftProp; - } - } - return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - } - const spread = spreadTypes[id] = createType(TypeFlags.Spread) as SpreadType; - Debug.assert(!!(left.flags & (TypeFlags.Spread | TypeFlags.Object)), "Left flags: " + left.flags.toString(2)); - Debug.assert(!!(right.flags & (TypeFlags.TypeParameter | TypeFlags.Intersection | TypeFlags.Index | TypeFlags.IndexedAccess | TypeFlags.Object)), "Right flags: " + right.flags.toString(2)); - spread.symbol = symbol; - spread.left = left as SpreadType | ResolvedType; - spread.right = right as TypeParameter | IntersectionType | IndexType | IndexedAccessType | ResolvedType; - spread.aliasSymbol = aliasSymbol; - spread.aliasTypeArguments = aliasTypeArguments; - return spread; - } - - function resolveObjectIntersection(intersection: IntersectionType): IntersectionType | ResolvedType { - if (find(intersection.types, t => !(t.flags & TypeFlags.Object))) { - return intersection; - } - const properties = getPropertiesOfType(intersection); + function getSpreadType(left: Type, right: Type, symbol: Symbol): ResolvedType { + Debug.assert(!!(left.flags & TypeFlags.Object) && !!(right.flags & TypeFlags.Object), "Only object types may be spread."); const members = createMap(); - for (const property of properties) { - members[property.name] = property; + const skippedPrivateMembers = createMap(); + const stringIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.String), getIndexInfoOfType(right, IndexKind.String)); + const numberIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.Number), getIndexInfoOfType(right, IndexKind.Number)); + + const isFromSpread = right.symbol !== symbol; + for (const rightProp of getPropertiesOfType(right)) { + if (getDeclarationModifierFlagsFromSymbol(rightProp) & (ModifierFlags.Private | ModifierFlags.Protected)) { + skippedPrivateMembers[rightProp.name] = true; + } + else if (!(rightProp.flags & SymbolFlags.Method && isFromSpread) && + !(rightProp.flags & SymbolFlags.SetAccessor && !(rightProp.flags & SymbolFlags.GetAccessor))) { + // skip methods from spreads and accessors with setters but no getters + members[rightProp.name] = rightProp; + } } - const stringIndex = getIndexInfoOfType(intersection, IndexKind.String); - const numberIndex = getIndexInfoOfType(intersection, IndexKind.Number); - return createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndex, numberIndex); + for (const leftProp of getPropertiesOfType(left)) { + if (leftProp.flags & SymbolFlags.SetAccessor && !(leftProp.flags & SymbolFlags.GetAccessor) + || leftProp.name in skippedPrivateMembers) { + continue; + } + if (leftProp.name in members) { + const rightProp = members[leftProp.name]; + if (rightProp.flags & SymbolFlags.Optional) { + const declarations: Declaration[] = concatenate(leftProp.declarations, rightProp.declarations); + const flags = SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | (leftProp.flags & SymbolFlags.Optional); + const result = createSymbol(flags, leftProp.name); + result.syntheticKind = SyntheticSymbolKind.Spread; + result.leftSpread = leftProp; + result.rightSpread = rightProp; + result.declarations = declarations; + if (declarations.length) { + result.valueDeclaration = declarations[0]; + } + result.isReadonly = isReadonlySymbol(leftProp) || isReadonlySymbol(rightProp); + members[leftProp.name] = result; + } + } + else { + members[leftProp.name] = leftProp; + } + } + return createAnonymousType(symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); } function createLiteralType(flags: TypeFlags, text: string) { @@ -6535,10 +6346,6 @@ namespace ts { if (type.flags & TypeFlags.Intersection) { return getIntersectionType(instantiateList((type).types, mapper, instantiateType), type.aliasSymbol, mapper.targetTypes); } - if (type.flags & TypeFlags.Spread) { - const spread = type as SpreadType; - return getSpreadType(instantiateType(spread.left, mapper), instantiateType(spread.right, mapper), type.symbol, type.aliasSymbol, mapper.targetTypes); - } if (type.flags & TypeFlags.Index) { return getIndexType(instantiateType((type).type, mapper)); } @@ -7089,30 +6896,7 @@ namespace ts { } } - if (source.flags & TypeFlags.Spread && target.flags & TypeFlags.Spread) { - // you only see this for spreads with type parameters - if (!(spreadTypeRelatedTo(source as SpreadType, target as SpreadType, /*atRightEdge*/ true))) { - if (reportErrors) { - reportRelationError(headMessage, source, target); - } - return Ternary.False; - } - const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo; - const apparentSource = getApparentType(source); - if (result = objectTypeRelatedTo(apparentSource, source, getApparentType(target), reportStructuralErrors)) { - errorInfo = saveErrorInfo; - return result; - } - } - if (source.flags & TypeFlags.TypeParameter) { - if (target.flags & TypeFlags.Spread) { - // T is assignable to ...T - if (source.symbol === (target as SpreadType).right.symbol - && (target as SpreadType).left === emptyObjectType) { - return Ternary.True; - } - } let constraint = getConstraintOfTypeParameter(source); if (!constraint || constraint.flags & TypeFlags.Any) { @@ -7164,32 +6948,6 @@ namespace ts { return Ternary.False; } - function spreadTypeRelatedTo(source: SpreadType, target: SpreadType, atRightEdge?: boolean): boolean { - // If the right side of a spread type is ObjectType, then the left side must be a Spread. - // Structural compatibility of the spreads' object types are checked separately in isRelatedTo, - // so just skip them for now. - if (source.right.flags & TypeFlags.Object || target.right.flags & TypeFlags.Object) { - return atRightEdge && - spreadTypeRelatedTo(source.right.flags & TypeFlags.Object ? source.left as SpreadType : source, - target.right.flags & TypeFlags.Object ? target.left as SpreadType : target); - } - // If both right sides are type parameters, intersections, index types or indexed access types, - // then they must be identical for the spread types to be related. - // It also means that the left sides are either spread types or object types. - - // if one left is object and the other is spread, that means the second has another type parameter. which isn't allowed - if (target.right !== source.right) { - return false; - } - if (source.left.flags & TypeFlags.Spread && target.left.flags & TypeFlags.Spread) { - // If the left sides are both spread types, then recursively check them. - return spreadTypeRelatedTo(source.left as SpreadType, target.left as SpreadType); - } - // If the left sides are both object types, then we should be at the end and both should be emptyObjectType. - // If not, we can't know what properties might have been overwritten, so fail. - return source.left === emptyObjectType && target.left === emptyObjectType; - } - function isIdenticalTo(source: Type, target: Type): Ternary { let result: Ternary; if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) { @@ -11167,6 +10925,10 @@ namespace ts { typeFlags = 0; } const type = checkExpression((memberDecl as SpreadElementExpression).expression); + if (!(type.flags & TypeFlags.Object)) { + error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types); + return unknownType; + } spread = getSpreadType(spread, type, node.symbol); continue; } @@ -15403,13 +15165,6 @@ namespace ts { checkTypeForDuplicateIndexSignatures(node); checkObjectTypeForDuplicateDeclarations(node); } - if (find(node.members, p => p.kind === SyntaxKind.SpreadTypeElement)) { - for (const signature of filter(node.members, p => p.kind === SyntaxKind.IndexSignature || - p.kind === SyntaxKind.CallSignature || - p.kind === SyntaxKind.ConstructSignature)) { - error(signature, Diagnostics.Type_literals_with_spreads_cannot_contain_index_call_or_construct_signatures); - } - } } } @@ -17467,9 +17222,7 @@ namespace ts { // perform property check if property or indexer is declared in 'type' // this allows to rule out cases when both property and indexer are inherited from the base class let errorNode: Node; - if (prop.valueDeclaration.name.kind === SyntaxKind.ComputedPropertyName || - prop.parent === containingType.symbol || - containingType.flags & TypeFlags.Spread) { + if (prop.valueDeclaration.name.kind === SyntaxKind.ComputedPropertyName || prop.parent === containingType.symbol) { errorNode = prop.valueDeclaration; } else if (indexDeclaration) { @@ -20699,12 +20452,6 @@ namespace ts { checkGrammarHeritageClause(heritageClause); } } - - let result: TypeElement; - if (result = find(node.members, e => e.kind === SyntaxKind.SpreadTypeElement)) { - return grammarErrorOnNode(result, Diagnostics.Interface_declaration_cannot_contain_a_spread_property); - } - return false; } diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 7a23ba8722b..0bba375a2cb 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1138,13 +1138,6 @@ namespace ts { writeLine(); } - function emitSpreadTypeElement(type: SpreadTypeElement) { - write("..."); - emitType(type.type); - write(";"); - writeLine(); - } - function emitVariableDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration) { // If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted // so there is no check needed to see if declaration is visible @@ -1729,8 +1722,6 @@ namespace ts { case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: return emitPropertyDeclaration(node); - case SyntaxKind.SpreadTypeElement: - return emitSpreadTypeElement(node as SpreadTypeElement); case SyntaxKind.EnumMember: return emitEnumMemberDeclaration(node); case SyntaxKind.ExportAssignment: diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 1d45e96cb6f..58c59b18f5e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1983,14 +1983,10 @@ "category": "Error", "code": 2697 }, - "Interface declaration cannot contain a spread property.": { + "Spread types may only be created from object types.": { "category": "Error", "code": 2698 }, - "Type literals with spreads cannot contain index, call or construct signatures.": { - "category": "Error", - "code": 2699 - }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ac41d78bb12..464f6ca01d8 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -76,8 +76,6 @@ namespace ts { visitNode(cbNode, (node).objectAssignmentInitializer); case SyntaxKind.SpreadElementExpression: return visitNode(cbNode, (node).expression); - case SyntaxKind.SpreadTypeElement: - return visitNode(cbNode, (node as SpreadTypeElement).type); case SyntaxKind.Parameter: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -2346,10 +2344,6 @@ namespace ts { if (token() === SyntaxKind.OpenBracketToken) { return true; } - // spread elements are type members - if (token() === SyntaxKind.DotDotDotToken) { - return true; - } // Try to get the first property-like token following all modifiers if (isLiteralPropertyName()) { idToken = token(); @@ -2375,9 +2369,6 @@ namespace ts { if (token() === SyntaxKind.NewKeyword && lookAhead(isStartOfConstructSignature)) { return parseSignatureMember(SyntaxKind.ConstructSignature); } - if (token() === SyntaxKind.DotDotDotToken) { - return parseSpreadTypeElement(); - } const fullStart = getNodePos(); const modifiers = parseModifiers(); if (isIndexSignature()) { @@ -2386,14 +2377,6 @@ namespace ts { return parsePropertyOrMethodSignature(fullStart, modifiers); } - function parseSpreadTypeElement() { - const element = createNode(SyntaxKind.SpreadTypeElement, scanner.getStartPos()) as SpreadTypeElement; - parseTokenNode(); // parse `...` - element.type = parseType(); - parseTypeMemberSemicolon(); - return finishNode(element); - } - function isStartOfConstructSignature() { nextToken(); return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ba5e6b2db99..d3b4cb3b6e7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -321,8 +321,6 @@ namespace ts { PropertyAssignment, ShorthandPropertyAssignment, SpreadElementExpression, - SpreadTypeElement, - // Enum EnumMember, @@ -664,11 +662,6 @@ namespace ts { initializer?: Expression; // Optional initializer } - // @kind(SyntaxKind.SpreadTypeElement) - export interface SpreadTypeElement extends TypeElement { - type: TypeNode; - } - // @kind(SyntaxKind.PropertyDeclaration) export interface PropertyDeclaration extends ClassElement { kind: SyntaxKind.PropertyDeclaration; @@ -2521,7 +2514,7 @@ namespace ts { Merged = 0x02000000, // Merged symbol (created during program binding) Transient = 0x04000000, // Transient symbol (created during type check) Prototype = 0x08000000, // Prototype property (no source representation) - SyntheticProperty = 0x10000000, // Property in union, intersection or spread type + SyntheticProperty = 0x10000000, // Property in union or intersection type Optional = 0x20000000, // Optional property ExportStar = 0x40000000, // Export * declaration @@ -2711,7 +2704,6 @@ namespace ts { ContainsObjectLiteral = 1 << 22, // Type is or contains object literal type /* @internal */ ContainsAnyFunctionType = 1 << 23, // Type is or contains object literal type - Spread = 1 << 24, // Spread types /* @internal */ Nullable = Undefined | Null, @@ -2729,12 +2721,12 @@ namespace ts { BooleanLike = Boolean | BooleanLiteral, EnumLike = Enum | EnumLiteral, UnionOrIntersection = Union | Intersection, - StructuredType = Object | Union | Intersection | Spread, + StructuredType = Object | Union | Intersection, StructuredOrTypeParameter = StructuredType | TypeParameter, // 'Narrowable' types are types where narrowing actually narrows. // This *should* be every type other than null, undefined, void, and never - Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol | Spread, + Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol, NotUnionOrUnit = Any | ESSymbol | Object, /* @internal */ RequiresWidening = ContainsWideningType | ContainsObjectLiteral, @@ -2849,12 +2841,6 @@ namespace ts { export type StructuredType = ObjectType | UnionType | IntersectionType; - /* @internal */ - export interface SpreadType extends Type { - left: SpreadType | ResolvedType; - right: TypeParameter | IntersectionType | IndexType | IndexedAccessType | ResolvedType; - } - /* @internal */ // An instantiated anonymous type has a target and a mapper export interface AnonymousType extends ObjectType { @@ -2868,7 +2854,7 @@ namespace ts { } /* @internal */ - // Resolved object, spread, union, or intersection type + // Resolved object, union, or intersection type export interface ResolvedType extends ObjectType, UnionOrIntersectionType { members: SymbolTable; // Properties by name properties: Symbol[]; // Properties diff --git a/src/lib/es2015.core.d.ts b/src/lib/es2015.core.d.ts index cc61445effe..28f2e12248b 100644 --- a/src/lib/es2015.core.d.ts +++ b/src/lib/es2015.core.d.ts @@ -278,7 +278,7 @@ interface ObjectConstructor { * @param target The target object to copy to. * @param source The source object from which to copy properties. */ - assign(target: T, source: U): { ...T, ...U }; + assign(target: T, source: U): T & U; /** * Copy the values of all of the enumerable own properties from one or more source objects to a @@ -287,7 +287,7 @@ interface ObjectConstructor { * @param source1 The first source object from which to copy properties. * @param source2 The second source object from which to copy properties. */ - assign(target: T, source1: U, source2: V): { ...T, ...U, ...V }; + assign(target: T, source1: U, source2: V): T & U & V; /** * Copy the values of all of the enumerable own properties from one or more source objects to a @@ -297,7 +297,7 @@ interface ObjectConstructor { * @param source2 The second source object from which to copy properties. * @param source3 The third source object from which to copy properties. */ - assign(target: T, source1: U, source2: V, source3: W): { ...T, ...U, ...V, ...W }; + assign(target: T, source1: U, source2: V, source3: W): T & U & V & W; /** * Copy the values of all of the enumerable own properties from one or more source objects to a From a6320203bec279d0d8db6ce9d479aba29ef0d388 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 2 Nov 2016 16:31:04 -0700 Subject: [PATCH 2/4] Fix lint --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c6924e2cb0a..872aad6b046 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4526,7 +4526,7 @@ namespace ts { * type itself. Note that the apparent type of a union type is the union type itself. */ function getApparentType(type: Type): Type { - let t = type.flags & TypeFlags.TypeParameter ? getApparentTypeOfTypeParameter(type) : type; + const t = type.flags & TypeFlags.TypeParameter ? getApparentTypeOfTypeParameter(type) : type; return t.flags & TypeFlags.StringLike ? globalStringType : t.flags & TypeFlags.NumberLike ? globalNumberType : t.flags & TypeFlags.BooleanLike ? globalBooleanType : From a077fd104aa6be0237bc6dfe00f57528c6fb89e1 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 3 Nov 2016 09:39:58 -0700 Subject: [PATCH 3/4] Remove spread type tests from spread tests --- tests/baselines/reference/objectSpread.js | 47 +--- .../baselines/reference/objectSpread.symbols | 223 +++++------------- tests/baselines/reference/objectSpread.types | 140 +---------- .../reference/objectSpreadGeneric.errors.txt | 148 ------------ .../reference/objectSpreadGeneric.js | 141 ----------- .../objectSpreadIndexSignature.errors.txt | 35 --- .../reference/objectSpreadIndexSignature.js | 56 ++--- .../objectSpreadIndexSignature.symbols | 42 ++++ .../objectSpreadIndexSignature.types | 52 ++++ .../reference/objectSpreadNegative.errors.txt | 141 ++++++----- .../reference/objectSpreadNegative.js | 86 +++---- .../objectSpreadNegativeParse.errors.txt | 14 +- .../types/spread/interfaceSpread.ts | 8 - .../conformance/types/spread/objectSpread.ts | 23 +- .../types/spread/objectSpreadGeneric.ts | 72 ------ .../spread/objectSpreadIndexSignature.ts | 25 +- .../types/spread/objectSpreadInference.ts | 19 -- .../types/spread/objectSpreadIntersection.ts | 36 --- .../types/spread/objectSpreadNegative.ts | 47 ++-- .../types/spread/objectSpreadScenarios.ts | 17 -- .../types/spread/objectSpreadUnion.ts | 23 -- .../fourslash/findAllRefsForObjectSpread.ts | 4 +- .../fourslash/goToDefinitionObjectSpread.ts | 4 +- tests/cases/fourslash/renameObjectSpread.ts | 4 +- 24 files changed, 350 insertions(+), 1057 deletions(-) delete mode 100644 tests/baselines/reference/objectSpreadGeneric.errors.txt delete mode 100644 tests/baselines/reference/objectSpreadGeneric.js delete mode 100644 tests/baselines/reference/objectSpreadIndexSignature.errors.txt create mode 100644 tests/baselines/reference/objectSpreadIndexSignature.symbols create mode 100644 tests/baselines/reference/objectSpreadIndexSignature.types delete mode 100644 tests/cases/conformance/types/spread/interfaceSpread.ts delete mode 100644 tests/cases/conformance/types/spread/objectSpreadGeneric.ts delete mode 100644 tests/cases/conformance/types/spread/objectSpreadInference.ts delete mode 100644 tests/cases/conformance/types/spread/objectSpreadIntersection.ts delete mode 100644 tests/cases/conformance/types/spread/objectSpreadScenarios.ts delete mode 100644 tests/cases/conformance/types/spread/objectSpreadUnion.ts diff --git a/tests/baselines/reference/objectSpread.js b/tests/baselines/reference/objectSpread.js index 23729d4cd6f..c19ead478cb 100644 --- a/tests/baselines/reference/objectSpread.js +++ b/tests/baselines/reference/objectSpread.js @@ -35,13 +35,8 @@ let getter: { a: number, c: number } = { ...op, c: 7 } getter.a = 12; -// null, undefined, functions and primitives result in { } -let spreadNull = { ...null }; -let spreadUndefind = { ...undefined }; -let spreadNum = { ...12 }; -let spreadBool = { ...false }; +// functions result in { } let spreadFunc = { ...(function () { }) }; -let spreadStr = { ...'foo' }; // methods are not enumerable class C { p = 1; m() { } } @@ -80,22 +75,6 @@ let computedAfter: { a: number, b: string, "at the end": number } = let a = 12; let shortCutted: { a: number, b: string } = { ...o, a } -// generics -function f(t: T, u: U): { ...T, ...U, id: string } { - return { ...t, ...u, id: 'id' }; -} -let exclusive: { id: string, a: number, b: string, c: string, d: boolean } = - f({ a: 1, b: 'yes' }, { c: 'no', d: false }) -let overlap: { id: string, a: number, b: string } = - f({ a: 1 }, { a: 2, b: 'extra' }) -let overlapConflict: { id:string, a: string } = - f({ a: 1 }, { a: 'mismatch' }) -let overwriteId: { id: string, a: number, c: number, d: string } = - f({ a: 1, id: true }, { c: 1, d: 'no' }) - -class D { m() { }; q = 2; } -let classesAreWrong: { id: string, ...C, ...D } = - f(new C(), new D()) //// [objectSpread.js] @@ -128,13 +107,8 @@ var propertyNested = __assign({ a: __assign({}, o) }); var op = { get a() { return 6; } }; var getter = __assign({}, op, { c: 7 }); getter.a = 12; -// null, undefined, functions and primitives result in { } -var spreadNull = __assign({}, null); -var spreadUndefind = __assign({}, undefined); -var spreadNum = __assign({}, 12); -var spreadBool = __assign({}, false); +// functions result in { } var spreadFunc = __assign({}, (function () { })); -var spreadStr = __assign({}, 'foo'); // methods are not enumerable var C = (function () { function C() { @@ -167,21 +141,4 @@ var computedAfter = __assign({}, o, (_c = { b: 'yeah' }, _c['at the end'] = 14, // shortcut syntax var a = 12; var shortCutted = __assign({}, o, { a: a }); -// generics -function f(t, u) { - return __assign({}, t, u, { id: 'id' }); -} -var exclusive = f({ a: 1, b: 'yes' }, { c: 'no', d: false }); -var overlap = f({ a: 1 }, { a: 2, b: 'extra' }); -var overlapConflict = f({ a: 1 }, { a: 'mismatch' }); -var overwriteId = f({ a: 1, id: true }, { c: 1, d: 'no' }); -var D = (function () { - function D() { - this.q = 2; - } - D.prototype.m = function () { }; - ; - return D; -}()); -var classesAreWrong = f(new C(), new D()); var _a, _b, _c; diff --git a/tests/baselines/reference/objectSpread.symbols b/tests/baselines/reference/objectSpread.symbols index 039be9e0d7d..b95f8273724 100644 --- a/tests/baselines/reference/objectSpread.symbols +++ b/tests/baselines/reference/objectSpread.symbols @@ -150,224 +150,127 @@ getter.a = 12; >getter : Symbol(getter, Decl(objectSpread.ts, 32, 3)) >a : Symbol(a, Decl(objectSpread.ts, 32, 13)) -// null, undefined, functions and primitives result in { } -let spreadNull = { ...null }; ->spreadNull : Symbol(spreadNull, Decl(objectSpread.ts, 37, 3)) - -let spreadUndefind = { ...undefined }; ->spreadUndefind : Symbol(spreadUndefind, Decl(objectSpread.ts, 38, 3)) - -let spreadNum = { ...12 }; ->spreadNum : Symbol(spreadNum, Decl(objectSpread.ts, 39, 3)) - -let spreadBool = { ...false }; ->spreadBool : Symbol(spreadBool, Decl(objectSpread.ts, 40, 3)) - +// functions result in { } let spreadFunc = { ...(function () { }) }; ->spreadFunc : Symbol(spreadFunc, Decl(objectSpread.ts, 41, 3)) - -let spreadStr = { ...'foo' }; ->spreadStr : Symbol(spreadStr, Decl(objectSpread.ts, 42, 3)) +>spreadFunc : Symbol(spreadFunc, Decl(objectSpread.ts, 37, 3)) // methods are not enumerable class C { p = 1; m() { } } ->C : Symbol(C, Decl(objectSpread.ts, 42, 29)) ->p : Symbol(C.p, Decl(objectSpread.ts, 45, 9)) ->m : Symbol(C.m, Decl(objectSpread.ts, 45, 16)) +>C : Symbol(C, Decl(objectSpread.ts, 37, 42)) +>p : Symbol(C.p, Decl(objectSpread.ts, 40, 9)) +>m : Symbol(C.m, Decl(objectSpread.ts, 40, 16)) let c: C = new C() ->c : Symbol(c, Decl(objectSpread.ts, 46, 3)) ->C : Symbol(C, Decl(objectSpread.ts, 42, 29)) ->C : Symbol(C, Decl(objectSpread.ts, 42, 29)) +>c : Symbol(c, Decl(objectSpread.ts, 41, 3)) +>C : Symbol(C, Decl(objectSpread.ts, 37, 42)) +>C : Symbol(C, Decl(objectSpread.ts, 37, 42)) let spreadC: { p: number } = { ...c } ->spreadC : Symbol(spreadC, Decl(objectSpread.ts, 47, 3)) ->p : Symbol(p, Decl(objectSpread.ts, 47, 14)) +>spreadC : Symbol(spreadC, Decl(objectSpread.ts, 42, 3)) +>p : Symbol(p, Decl(objectSpread.ts, 42, 14)) // own methods are enumerable let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } }; ->cplus : Symbol(cplus, Decl(objectSpread.ts, 50, 3)) ->p : Symbol(p, Decl(objectSpread.ts, 50, 12)) ->plus : Symbol(plus, Decl(objectSpread.ts, 50, 23)) ->plus : Symbol(plus, Decl(objectSpread.ts, 50, 48)) +>cplus : Symbol(cplus, Decl(objectSpread.ts, 45, 3)) +>p : Symbol(p, Decl(objectSpread.ts, 45, 12)) +>plus : Symbol(plus, Decl(objectSpread.ts, 45, 23)) +>plus : Symbol(plus, Decl(objectSpread.ts, 45, 48)) cplus.plus(); ->cplus.plus : Symbol(plus, Decl(objectSpread.ts, 50, 23)) ->cplus : Symbol(cplus, Decl(objectSpread.ts, 50, 3)) ->plus : Symbol(plus, Decl(objectSpread.ts, 50, 23)) +>cplus.plus : Symbol(plus, Decl(objectSpread.ts, 45, 23)) +>cplus : Symbol(cplus, Decl(objectSpread.ts, 45, 3)) +>plus : Symbol(plus, Decl(objectSpread.ts, 45, 23)) // new field's type conflicting with existing field is OK let changeTypeAfter: { a: string, b: string } = ->changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 54, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 54, 22)) ->b : Symbol(b, Decl(objectSpread.ts, 54, 33)) +>changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 49, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 49, 22)) +>b : Symbol(b, Decl(objectSpread.ts, 49, 33)) { ...o, a: 'wrong type?' } ->a : Symbol(a, Decl(objectSpread.ts, 55, 11)) +>a : Symbol(a, Decl(objectSpread.ts, 50, 11)) let changeTypeBefore: { a: number, b: string } = ->changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 56, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 56, 23)) ->b : Symbol(b, Decl(objectSpread.ts, 56, 34)) +>changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 51, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 51, 23)) +>b : Symbol(b, Decl(objectSpread.ts, 51, 34)) { a: 'wrong type?', ...o }; ->a : Symbol(a, Decl(objectSpread.ts, 57, 5)) +>a : Symbol(a, Decl(objectSpread.ts, 52, 5)) let changeTypeBoth: { a: string, b: number } = ->changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 58, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 58, 21)) ->b : Symbol(b, Decl(objectSpread.ts, 58, 32)) +>changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 53, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 53, 21)) +>b : Symbol(b, Decl(objectSpread.ts, 53, 32)) { ...o, ...swap }; // optional let definiteBoolean: { sn: boolean }; ->definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 62, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 62, 22)) +>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 57, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 57, 22)) let definiteString: { sn: string }; ->definiteString : Symbol(definiteString, Decl(objectSpread.ts, 63, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 63, 21)) +>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 58, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 58, 21)) let optionalString: { sn?: string }; ->optionalString : Symbol(optionalString, Decl(objectSpread.ts, 64, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 64, 21)) +>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 59, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 59, 21)) let optionalNumber: { sn?: number }; ->optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 65, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 65, 21)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 60, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 60, 21)) let optionalUnionStops: { sn: string | number | boolean } = { ...definiteBoolean, ...definiteString, ...optionalNumber }; ->optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 66, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 66, 25)) +>optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 61, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 61, 25)) let optionalUnionDuplicates: { sn: string | number } = { ...definiteBoolean, ...definiteString, ...optionalString, ...optionalNumber }; ->optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 67, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 67, 30)) +>optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 62, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 62, 30)) let allOptional: { sn?: string | number } = { ...optionalString, ...optionalNumber }; ->allOptional : Symbol(allOptional, Decl(objectSpread.ts, 68, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 68, 18)) +>allOptional : Symbol(allOptional, Decl(objectSpread.ts, 63, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 63, 18)) // computed property let computedFirst: { a: number, b: string, "before everything": number } = ->computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 71, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 71, 20)) ->b : Symbol(b, Decl(objectSpread.ts, 71, 31)) +>computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 66, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 66, 20)) +>b : Symbol(b, Decl(objectSpread.ts, 66, 31)) { ['before everything']: 12, ...o, b: 'yes' } ->'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 72, 5)) ->b : Symbol(b, Decl(objectSpread.ts, 72, 38)) +>'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 67, 5)) +>b : Symbol(b, Decl(objectSpread.ts, 67, 38)) let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = ->computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 73, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 73, 21)) ->b : Symbol(b, Decl(objectSpread.ts, 73, 32)) ->c : Symbol(c, Decl(objectSpread.ts, 73, 43)) +>computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 68, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 68, 21)) +>b : Symbol(b, Decl(objectSpread.ts, 68, 32)) +>c : Symbol(c, Decl(objectSpread.ts, 68, 43)) { ...o, ['in the middle']: 13, b: 'maybe?', ...o2 } ->'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 74, 11)) ->b : Symbol(b, Decl(objectSpread.ts, 74, 34)) +>'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 69, 11)) +>b : Symbol(b, Decl(objectSpread.ts, 69, 34)) let computedAfter: { a: number, b: string, "at the end": number } = ->computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 75, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 75, 20)) ->b : Symbol(b, Decl(objectSpread.ts, 75, 31)) +>computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 70, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 70, 20)) +>b : Symbol(b, Decl(objectSpread.ts, 70, 31)) { ...o, b: 'yeah', ['at the end']: 14 } ->b : Symbol(b, Decl(objectSpread.ts, 76, 11)) ->'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 76, 22)) +>b : Symbol(b, Decl(objectSpread.ts, 71, 11)) +>'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 71, 22)) // shortcut syntax let a = 12; ->a : Symbol(a, Decl(objectSpread.ts, 78, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 73, 3)) let shortCutted: { a: number, b: string } = { ...o, a } ->shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 79, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 79, 18)) ->b : Symbol(b, Decl(objectSpread.ts, 79, 29)) ->a : Symbol(a, Decl(objectSpread.ts, 79, 51)) +>shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 74, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 74, 18)) +>b : Symbol(b, Decl(objectSpread.ts, 74, 29)) +>a : Symbol(a, Decl(objectSpread.ts, 74, 51)) -// generics -function f(t: T, u: U): { ...T, ...U, id: string } { ->f : Symbol(f, Decl(objectSpread.ts, 79, 55)) ->T : Symbol(T, Decl(objectSpread.ts, 82, 11)) ->U : Symbol(U, Decl(objectSpread.ts, 82, 13)) ->t : Symbol(t, Decl(objectSpread.ts, 82, 17)) ->T : Symbol(T, Decl(objectSpread.ts, 82, 11)) ->u : Symbol(u, Decl(objectSpread.ts, 82, 22)) ->U : Symbol(U, Decl(objectSpread.ts, 82, 13)) ->T : Symbol(T, Decl(objectSpread.ts, 82, 11)) ->U : Symbol(U, Decl(objectSpread.ts, 82, 13)) ->id : Symbol(id, Decl(objectSpread.ts, 82, 43)) - - return { ...t, ...u, id: 'id' }; ->id : Symbol(id, Decl(objectSpread.ts, 83, 24)) -} -let exclusive: { id: string, a: number, b: string, c: string, d: boolean } = ->exclusive : Symbol(exclusive, Decl(objectSpread.ts, 85, 3)) ->id : Symbol(id, Decl(objectSpread.ts, 85, 16)) ->a : Symbol(a, Decl(objectSpread.ts, 85, 28)) ->b : Symbol(b, Decl(objectSpread.ts, 85, 39)) ->c : Symbol(c, Decl(objectSpread.ts, 85, 50)) ->d : Symbol(d, Decl(objectSpread.ts, 85, 61)) - - f({ a: 1, b: 'yes' }, { c: 'no', d: false }) ->f : Symbol(f, Decl(objectSpread.ts, 79, 55)) ->a : Symbol(a, Decl(objectSpread.ts, 86, 7)) ->b : Symbol(b, Decl(objectSpread.ts, 86, 13)) ->c : Symbol(c, Decl(objectSpread.ts, 86, 27)) ->d : Symbol(d, Decl(objectSpread.ts, 86, 36)) - -let overlap: { id: string, a: number, b: string } = ->overlap : Symbol(overlap, Decl(objectSpread.ts, 87, 3)) ->id : Symbol(id, Decl(objectSpread.ts, 87, 14)) ->a : Symbol(a, Decl(objectSpread.ts, 87, 26)) ->b : Symbol(b, Decl(objectSpread.ts, 87, 37)) - - f({ a: 1 }, { a: 2, b: 'extra' }) ->f : Symbol(f, Decl(objectSpread.ts, 79, 55)) ->a : Symbol(a, Decl(objectSpread.ts, 88, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 88, 17)) ->b : Symbol(b, Decl(objectSpread.ts, 88, 23)) - -let overlapConflict: { id:string, a: string } = ->overlapConflict : Symbol(overlapConflict, Decl(objectSpread.ts, 89, 3)) ->id : Symbol(id, Decl(objectSpread.ts, 89, 22)) ->a : Symbol(a, Decl(objectSpread.ts, 89, 33)) - - f({ a: 1 }, { a: 'mismatch' }) ->f : Symbol(f, Decl(objectSpread.ts, 79, 55)) ->a : Symbol(a, Decl(objectSpread.ts, 90, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 90, 17)) - -let overwriteId: { id: string, a: number, c: number, d: string } = ->overwriteId : Symbol(overwriteId, Decl(objectSpread.ts, 91, 3)) ->id : Symbol(id, Decl(objectSpread.ts, 91, 18)) ->a : Symbol(a, Decl(objectSpread.ts, 91, 30)) ->c : Symbol(c, Decl(objectSpread.ts, 91, 41)) ->d : Symbol(d, Decl(objectSpread.ts, 91, 52)) - - f({ a: 1, id: true }, { c: 1, d: 'no' }) ->f : Symbol(f, Decl(objectSpread.ts, 79, 55)) ->a : Symbol(a, Decl(objectSpread.ts, 92, 7)) ->id : Symbol(id, Decl(objectSpread.ts, 92, 13)) ->c : Symbol(c, Decl(objectSpread.ts, 92, 27)) ->d : Symbol(d, Decl(objectSpread.ts, 92, 33)) - -class D { m() { }; q = 2; } ->D : Symbol(D, Decl(objectSpread.ts, 92, 44)) ->m : Symbol(D.m, Decl(objectSpread.ts, 94, 9)) ->q : Symbol(D.q, Decl(objectSpread.ts, 94, 18)) - -let classesAreWrong: { id: string, ...C, ...D } = ->classesAreWrong : Symbol(classesAreWrong, Decl(objectSpread.ts, 95, 3)) ->id : Symbol(id, Decl(objectSpread.ts, 95, 22)) ->C : Symbol(C, Decl(objectSpread.ts, 42, 29)) ->D : Symbol(D, Decl(objectSpread.ts, 92, 44)) - - f(new C(), new D()) ->f : Symbol(f, Decl(objectSpread.ts, 79, 55)) ->C : Symbol(C, Decl(objectSpread.ts, 42, 29)) ->D : Symbol(D, Decl(objectSpread.ts, 92, 44)) diff --git a/tests/baselines/reference/objectSpread.types b/tests/baselines/reference/objectSpread.types index 78f4f7583d9..e9b9a6421c2 100644 --- a/tests/baselines/reference/objectSpread.types +++ b/tests/baselines/reference/objectSpread.types @@ -223,36 +223,13 @@ getter.a = 12; >a : number >12 : 12 -// null, undefined, functions and primitives result in { } -let spreadNull = { ...null }; ->spreadNull : {} ->{ ...null } : {} ->null : null - -let spreadUndefind = { ...undefined }; ->spreadUndefind : {} ->{ ...undefined } : {} ->undefined : any - -let spreadNum = { ...12 }; ->spreadNum : {} ->{ ...12 } : {} - -let spreadBool = { ...false }; ->spreadBool : {} ->{ ...false } : {} ->false : false - +// functions result in { } let spreadFunc = { ...(function () { }) }; >spreadFunc : {} >{ ...(function () { }) } : {} >(function () { }) : () => void >function () { } : () => void -let spreadStr = { ...'foo' }; ->spreadStr : {} ->{ ...'foo' } : {} - // methods are not enumerable class C { p = 1; m() { } } >C : C @@ -421,119 +398,4 @@ let shortCutted: { a: number, b: string } = { ...o, a } >o : any >a : number -// generics -function f(t: T, u: U): { ...T, ...U, id: string } { ->f : (t: T, u: U) => { ...T; ...U; id: string; } ->T : T ->U : U ->t : T ->T : T ->u : U ->U : U ->T : T ->U : U ->id : string - - return { ...t, ...u, id: 'id' }; ->{ ...t, ...u, id: 'id' } : { ...T; ...U; id: string; } ->t : any ->u : any ->id : string ->'id' : "id" -} -let exclusive: { id: string, a: number, b: string, c: string, d: boolean } = ->exclusive : { id: string; a: number; b: string; c: string; d: boolean; } ->id : string ->a : number ->b : string ->c : string ->d : boolean - - f({ a: 1, b: 'yes' }, { c: 'no', d: false }) ->f({ a: 1, b: 'yes' }, { c: 'no', d: false }) : { id: string; c: string; d: boolean; a: number; b: string; } ->f : (t: T, u: U) => { ...T; ...U; id: string; } ->{ a: 1, b: 'yes' } : { a: number; b: string; } ->a : number ->1 : 1 ->b : string ->'yes' : "yes" ->{ c: 'no', d: false } : { c: string; d: false; } ->c : string ->'no' : "no" ->d : boolean ->false : false - -let overlap: { id: string, a: number, b: string } = ->overlap : { id: string; a: number; b: string; } ->id : string ->a : number ->b : string - - f({ a: 1 }, { a: 2, b: 'extra' }) ->f({ a: 1 }, { a: 2, b: 'extra' }) : { id: string; a: number; b: string; } ->f : (t: T, u: U) => { ...T; ...U; id: string; } ->{ a: 1 } : { a: number; } ->a : number ->1 : 1 ->{ a: 2, b: 'extra' } : { a: number; b: string; } ->a : number ->2 : 2 ->b : string ->'extra' : "extra" - -let overlapConflict: { id:string, a: string } = ->overlapConflict : { id: string; a: string; } ->id : string ->a : string - - f({ a: 1 }, { a: 'mismatch' }) ->f({ a: 1 }, { a: 'mismatch' }) : { id: string; a: string; } ->f : (t: T, u: U) => { ...T; ...U; id: string; } ->{ a: 1 } : { a: number; } ->a : number ->1 : 1 ->{ a: 'mismatch' } : { a: string; } ->a : string ->'mismatch' : "mismatch" - -let overwriteId: { id: string, a: number, c: number, d: string } = ->overwriteId : { id: string; a: number; c: number; d: string; } ->id : string ->a : number ->c : number ->d : string - - f({ a: 1, id: true }, { c: 1, d: 'no' }) ->f({ a: 1, id: true }, { c: 1, d: 'no' }) : { id: string; c: number; d: string; a: number; } ->f : (t: T, u: U) => { ...T; ...U; id: string; } ->{ a: 1, id: true } : { a: number; id: true; } ->a : number ->1 : 1 ->id : boolean ->true : true ->{ c: 1, d: 'no' } : { c: number; d: string; } ->c : number ->1 : 1 ->d : string ->'no' : "no" - -class D { m() { }; q = 2; } ->D : D ->m : () => void ->q : number ->2 : 2 - -let classesAreWrong: { id: string, ...C, ...D } = ->classesAreWrong : { q: number; p: number; id: string; } ->id : string ->C : C ->D : D - - f(new C(), new D()) ->f(new C(), new D()) : { id: string; q: number; p: number; } ->f : (t: T, u: U) => { ...T; ...U; id: string; } ->new C() : C ->C : typeof C ->new D() : D ->D : typeof D diff --git a/tests/baselines/reference/objectSpreadGeneric.errors.txt b/tests/baselines/reference/objectSpreadGeneric.errors.txt deleted file mode 100644 index f1e2b7e4828..00000000000 --- a/tests/baselines/reference/objectSpreadGeneric.errors.txt +++ /dev/null @@ -1,148 +0,0 @@ -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(9,5): error TS2322: Type '{ ...U }' is not assignable to type 'U'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(10,11): error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...V; ...U; ...T }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(11,11): error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...U; ...T; ...V }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(12,11): error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...U; ...V }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(13,11): error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...T; ...V }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(14,11): error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...T; ...U }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(16,11): error TS2322: Type '{ first: string; ...T; ...U }' is not assignable to type '{ first: string; ...T; ...U }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(19,11): error TS2322: Type '{}' is not assignable to type '{ ...T; ...U }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(26,11): error TS2322: Type '{ sn?: boolean; ...T; sn?: string | number; }' is not assignable to type '{ ...T; sn?: string | number | boolean; }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(32,11): error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(34,11): error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; second: string; ...T; third: string; }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(36,11): error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(38,11): error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }' is not assignable to type '{ first: string; second: string; secondsecond: string; third: string; ...T; ...U }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(42,11): error TS2322: Type '{ firrrrrrst: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(44,11): error TS2322: Type '{ first: string; ...T; ssssssssecond: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(46,11): error TS2322: Type '{ first: string; ...T; second: string; ...U; thirrrrrrrd: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(57,5): error TS2322: Type '{ ...keyof U }' is not assignable to type '{ ...keyof T }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(58,5): error TS2322: Type '{ ...keyof T }' is not assignable to type '{ ...keyof U }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(61,5): error TS2322: Type '{ ...K }' is not assignable to type '{ ...keyof T }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(62,5): error TS2322: Type '{ ...keyof T }' is not assignable to type '{ ...K }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(63,5): error TS2322: Type '{ ...J }' is not assignable to type '{ ...keyof U }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(64,5): error TS2322: Type '{ ...keyof U }' is not assignable to type '{ ...J }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(70,5): error TS2322: Type '{ ...U[J] }' is not assignable to type '{ ...T[K] }'. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(71,5): error TS2322: Type '{ ...T[K] }' is not assignable to type '{ ...U[J] }'. - - -==== tests/cases/conformance/types/spread/objectSpreadGeneric.ts (24 errors) ==== - function f(t: T, u: U, v: V): void { - let o: { ...T, ...U, ...V }; - let uus: { ...U, ...U}; - let us: { ...U }; - const same: { ...T, ...U, ...V } = o; // ok - uus = us; // ok, multiple spreads are equivalent to a single one - us = uus; // ok, multiple spreads are equivalent to a single one - us = u; // ok, type has at least all the properties of the spread - u = us; // error, might be missing a ton of stuff - ~ -!!! error TS2322: Type '{ ...U }' is not assignable to type 'U'. - const reversed: { ...V, ...U, ...T } = o; // error, reversed - ~~~~~~~~ -!!! error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...V; ...U; ...T }'. - const reversed2: { ...U, ...T, ...V } = o; // error, U and T are still reversed - ~~~~~~~~~ -!!! error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...U; ...T; ...V }'. - const missingT: { ...U, ...V } = o; // error, missing T - ~~~~~~~~ -!!! error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...U; ...V }'. - const missingU: { ...T, ...V } = o; // error, missing U - ~~~~~~~~ -!!! error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...T; ...V }'. - const missingV: { ...T, ...U } = o; // error, missing V - ~~~~~~~~ -!!! error TS2322: Type '{ ...T; ...U; ...V }' is not assignable to type '{ ...T; ...U }'. - const atEnd: { ...T, ...U, second: string } = { ...t, ...u, second: 'foo' }; // ok - const atBeginning: { first: string, ...T, ...U, } = { first: 'foo', ...t, ...u }; // error, not assignable - ~~~~~~~~~~~ -!!! error TS2322: Type '{ first: string; ...T; ...U }' is not assignable to type '{ first: string; ...T; ...U }'. - - const emptyTarget: { } = { ...t, ...u } // ok - const emptySource: { ...T, ...U } = { }; // error, {} is not assignable to U (or T) - ~~~~~~~~~~~ -!!! error TS2322: Type '{}' is not assignable to type '{ ...T; ...U }'. - - // error, { sn?: boolean } ...T ... { sn?: number | string } is not assignable to - // T ... { sn?: number | string | boolean } - let optionalNumber: { sn?: number }; - let optionalString: { sn?: string }; - let optionalBoolean: { sn?: boolean }; - const unionCutoff: { ...T, sn?: number | string | boolean } = - ~~~~~~~~~~~ -!!! error TS2322: Type '{ sn?: boolean; ...T; sn?: string | number; }' is not assignable to type '{ ...T; sn?: string | number | boolean; }'. - { ...optionalBoolean, ...t, ...optionalString, ...optionalNumber } - unionCutoff.sn; // ok - const optionalCutoff = { ...t, ...optionalNumber }; // ok - optionalCutoff.sn; // ok - - const interspersed: { first: string, ...T, second: string, ...U, third: string } = - ~~~~~~~~~~~~ -!!! error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. - { first: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable - const interspersedMissingU: { first: string, second: string, ...T, third: string } = - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; second: string; ...T; third: string; }'. - { first: '1', ...t, second: '2', ...u, third: '3' }; // error, 'U' is missing - const interspersedOrder1: { first: string, ...T, second: string, ...U, third: string, secondsecond: string } = - ~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }'. - { first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable - const interspersedOrder2: { first: string, second: string, secondsecond: string, third: string, ...T, ...U } = - ~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ first: string; ...T; second: string; ...U; third: string; secondsecond: string; }' is not assignable to type '{ first: string; second: string; secondsecond: string; third: string; ...T; ...U }'. - { first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable - - - const mismatchFirst: { first: string, ...T, second: string, ...U, third: string } = - ~~~~~~~~~~~~~ -!!! error TS2322: Type '{ firrrrrrst: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. - { firrrrrrst: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable - const mismatchSecond: { first: string, ...T, second: string, ...U, third: string } = - ~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ first: string; ...T; ssssssssecond: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. - { first: '1', ...t, ssssssssecond: '2', ...u, third: '3' }; // error, not assignable - const mismatchLast: { first: string, ...T, second: string, ...U, third: string } = - ~~~~~~~~~~~~ -!!! error TS2322: Type '{ first: string; ...T; second: string; ...U; thirrrrrrrd: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. - { first: '1', ...t, second: '2', ...u, thirrrrrrrd: '3' }; // error, not assignable - } - - function indexAccessedTest(t: T, u: U, key1: K, key2: J) { - let k1: { ...keyof T }; - let k2: { ...keyof U }; - let k3: { ...K }; - let k4: { ...J }; - k1 = k1; // ok - k2 = k2; // ok - k1 = k2; // error - ~~ -!!! error TS2322: Type '{ ...keyof U }' is not assignable to type '{ ...keyof T }'. - k2 = k1; // error - ~~ -!!! error TS2322: Type '{ ...keyof T }' is not assignable to type '{ ...keyof U }'. - k3 = k3; // ok - k4 = k4; // ok - k1 = k3; // error - ~~ -!!! error TS2322: Type '{ ...K }' is not assignable to type '{ ...keyof T }'. - k3 = k1; // error - ~~ -!!! error TS2322: Type '{ ...keyof T }' is not assignable to type '{ ...K }'. - k2 = k4; // error - ~~ -!!! error TS2322: Type '{ ...J }' is not assignable to type '{ ...keyof U }'. - k4 = k2; // error - ~~ -!!! error TS2322: Type '{ ...keyof U }' is not assignable to type '{ ...J }'. - - let i1: { ...T[K] }; - let i2: { ...U[J] }; - i1 = i1; // ok - i2 = i2; // ok - i1 = i2; // error - ~~ -!!! error TS2322: Type '{ ...U[J] }' is not assignable to type '{ ...T[K] }'. - i2 = i1; // error - ~~ -!!! error TS2322: Type '{ ...T[K] }' is not assignable to type '{ ...U[J] }'. - } - \ No newline at end of file diff --git a/tests/baselines/reference/objectSpreadGeneric.js b/tests/baselines/reference/objectSpreadGeneric.js deleted file mode 100644 index 8e89ebeef64..00000000000 --- a/tests/baselines/reference/objectSpreadGeneric.js +++ /dev/null @@ -1,141 +0,0 @@ -//// [objectSpreadGeneric.ts] -function f(t: T, u: U, v: V): void { - let o: { ...T, ...U, ...V }; - let uus: { ...U, ...U}; - let us: { ...U }; - const same: { ...T, ...U, ...V } = o; // ok - uus = us; // ok, multiple spreads are equivalent to a single one - us = uus; // ok, multiple spreads are equivalent to a single one - us = u; // ok, type has at least all the properties of the spread - u = us; // error, might be missing a ton of stuff - const reversed: { ...V, ...U, ...T } = o; // error, reversed - const reversed2: { ...U, ...T, ...V } = o; // error, U and T are still reversed - const missingT: { ...U, ...V } = o; // error, missing T - const missingU: { ...T, ...V } = o; // error, missing U - const missingV: { ...T, ...U } = o; // error, missing V - const atEnd: { ...T, ...U, second: string } = { ...t, ...u, second: 'foo' }; // ok - const atBeginning: { first: string, ...T, ...U, } = { first: 'foo', ...t, ...u }; // error, not assignable - - const emptyTarget: { } = { ...t, ...u } // ok - const emptySource: { ...T, ...U } = { }; // error, {} is not assignable to U (or T) - - // error, { sn?: boolean } ...T ... { sn?: number | string } is not assignable to - // T ... { sn?: number | string | boolean } - let optionalNumber: { sn?: number }; - let optionalString: { sn?: string }; - let optionalBoolean: { sn?: boolean }; - const unionCutoff: { ...T, sn?: number | string | boolean } = - { ...optionalBoolean, ...t, ...optionalString, ...optionalNumber } - unionCutoff.sn; // ok - const optionalCutoff = { ...t, ...optionalNumber }; // ok - optionalCutoff.sn; // ok - - const interspersed: { first: string, ...T, second: string, ...U, third: string } = - { first: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable - const interspersedMissingU: { first: string, second: string, ...T, third: string } = - { first: '1', ...t, second: '2', ...u, third: '3' }; // error, 'U' is missing - const interspersedOrder1: { first: string, ...T, second: string, ...U, third: string, secondsecond: string } = - { first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable - const interspersedOrder2: { first: string, second: string, secondsecond: string, third: string, ...T, ...U } = - { first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable - - - const mismatchFirst: { first: string, ...T, second: string, ...U, third: string } = - { firrrrrrst: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable - const mismatchSecond: { first: string, ...T, second: string, ...U, third: string } = - { first: '1', ...t, ssssssssecond: '2', ...u, third: '3' }; // error, not assignable - const mismatchLast: { first: string, ...T, second: string, ...U, third: string } = - { first: '1', ...t, second: '2', ...u, thirrrrrrrd: '3' }; // error, not assignable -} - -function indexAccessedTest(t: T, u: U, key1: K, key2: J) { - let k1: { ...keyof T }; - let k2: { ...keyof U }; - let k3: { ...K }; - let k4: { ...J }; - k1 = k1; // ok - k2 = k2; // ok - k1 = k2; // error - k2 = k1; // error - k3 = k3; // ok - k4 = k4; // ok - k1 = k3; // error - k3 = k1; // error - k2 = k4; // error - k4 = k2; // error - - let i1: { ...T[K] }; - let i2: { ...U[J] }; - i1 = i1; // ok - i2 = i2; // ok - i1 = i2; // error - i2 = i1; // error -} - - -//// [objectSpreadGeneric.js] -var __assign = (this && this.__assign) || Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; -}; -function f(t, u, v) { - var o; - var uus; - var us; - var same = o; // ok - uus = us; // ok, multiple spreads are equivalent to a single one - us = uus; // ok, multiple spreads are equivalent to a single one - us = u; // ok, type has at least all the properties of the spread - u = us; // error, might be missing a ton of stuff - var reversed = o; // error, reversed - var reversed2 = o; // error, U and T are still reversed - var missingT = o; // error, missing T - var missingU = o; // error, missing U - var missingV = o; // error, missing V - var atEnd = __assign({}, t, u, { second: 'foo' }); // ok - var atBeginning = __assign({ first: 'foo' }, t, u); // error, not assignable - var emptyTarget = __assign({}, t, u); // ok - var emptySource = {}; // error, {} is not assignable to U (or T) - // error, { sn?: boolean } ...T ... { sn?: number | string } is not assignable to - // T ... { sn?: number | string | boolean } - var optionalNumber; - var optionalString; - var optionalBoolean; - var unionCutoff = __assign({}, optionalBoolean, t, optionalString, optionalNumber); - unionCutoff.sn; // ok - var optionalCutoff = __assign({}, t, optionalNumber); // ok - optionalCutoff.sn; // ok - var interspersed = __assign({ first: '1' }, t, { second: '2' }, u, { third: '3' }); // error, not assignable - var interspersedMissingU = __assign({ first: '1' }, t, { second: '2' }, u, { third: '3' }); // error, 'U' is missing - var interspersedOrder1 = __assign({ first: '1' }, t, { second: '2' }, u, { third: '3', secondsecond: 'false' }); // error, not assignable - var interspersedOrder2 = __assign({ first: '1' }, t, { second: '2' }, u, { third: '3', secondsecond: 'false' }); // error, not assignable - var mismatchFirst = __assign({ firrrrrrst: '1' }, t, { second: '2' }, u, { third: '3' }); // error, not assignable - var mismatchSecond = __assign({ first: '1' }, t, { ssssssssecond: '2' }, u, { third: '3' }); // error, not assignable - var mismatchLast = __assign({ first: '1' }, t, { second: '2' }, u, { thirrrrrrrd: '3' }); // error, not assignable -} -function indexAccessedTest(t, u, key1, key2) { - var k1; - var k2; - var k3; - var k4; - k1 = k1; // ok - k2 = k2; // ok - k1 = k2; // error - k2 = k1; // error - k3 = k3; // ok - k4 = k4; // ok - k1 = k3; // error - k3 = k1; // error - k2 = k4; // error - k4 = k2; // error - var i1; - var i2; - i1 = i1; // ok - i2 = i2; // ok - i1 = i2; // error - i2 = i1; // error -} diff --git a/tests/baselines/reference/objectSpreadIndexSignature.errors.txt b/tests/baselines/reference/objectSpreadIndexSignature.errors.txt deleted file mode 100644 index d3faa2e6ff8..00000000000 --- a/tests/baselines/reference/objectSpreadIndexSignature.errors.txt +++ /dev/null @@ -1,35 +0,0 @@ -tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts(6,39): error TS2699: Type literals with spreads cannot contain index, call or construct signatures. -tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts(24,20): error TS2699: Type literals with spreads cannot contain index, call or construct signatures. - - -==== tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts (2 errors) ==== - class C { - a: number; - c: boolean; - } - // index signatures are not allowed in object literals with spread types - let c: { ...C, b: string, c?: string, [n: number]: string }; - ~~~~~~~~~~~~~~~~~~~ -!!! error TS2699: Type literals with spreads cannot contain index, call or construct signatures. - let n: number = c.a; - let s: string = c[12]; - interface Indexed { - [n: string]: number; - a: number; - } - let i: { ...Indexed, b: number }; - n = i[101]; - n = i.b; - interface Indexed2 { - [n: string]: boolean; - c: boolean; - } - let ii: { ...Indexed, ...Indexed2, b: boolean, d: number }; - let nb: number | boolean = ii[1001]; - - function f(t: T) { - let i: { ...T, [n: number]: string }; - ~~~~~~~~~~~~~~~~~~~ -!!! error TS2699: Type literals with spreads cannot contain index, call or construct signatures. - } - \ No newline at end of file diff --git a/tests/baselines/reference/objectSpreadIndexSignature.js b/tests/baselines/reference/objectSpreadIndexSignature.js index ab18c0f24a9..22e92e6a844 100644 --- a/tests/baselines/reference/objectSpreadIndexSignature.js +++ b/tests/baselines/reference/objectSpreadIndexSignature.js @@ -1,46 +1,36 @@ //// [objectSpreadIndexSignature.ts] -class C { - a: number; - c: boolean; -} -// index signatures are not allowed in object literals with spread types -let c: { ...C, b: string, c?: string, [n: number]: string }; -let n: number = c.a; -let s: string = c[12]; interface Indexed { [n: string]: number; a: number; } -let i: { ...Indexed, b: number }; -n = i[101]; -n = i.b; interface Indexed2 { [n: string]: boolean; c: boolean; } -let ii: { ...Indexed, ...Indexed2, b: boolean, d: number }; -let nb: number | boolean = ii[1001]; - -function f(t: T) { - let i: { ...T, [n: number]: string }; -} +let indexed: Indexed; +let indexed2: Indexed2; +let i = { ...indexed, b: 11 }; +// only indexed has indexer, so i[101]: any +i[101]; +let ii = { ...indexed, ...indexed2 }; +// both have indexer, so i[1001]: number | boolean +ii[1001]; //// [objectSpreadIndexSignature.js] -var C = (function () { - function C() { +var __assign = (this && this.__assign) || Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; } - return C; -}()); -// index signatures are not allowed in object literals with spread types -var c; -var n = c.a; -var s = c[12]; -var i; -n = i[101]; -n = i.b; -var ii; -var nb = ii[1001]; -function f(t) { - var i; -} + return t; +}; +var indexed; +var indexed2; +var i = __assign({}, indexed, { b: 11 }); +// only indexed has indexer, so i[101]: any +i[101]; +var ii = __assign({}, indexed, indexed2); +// both have indexer, so i[1001]: number | boolean +ii[1001]; diff --git a/tests/baselines/reference/objectSpreadIndexSignature.symbols b/tests/baselines/reference/objectSpreadIndexSignature.symbols new file mode 100644 index 00000000000..c51e7f4532f --- /dev/null +++ b/tests/baselines/reference/objectSpreadIndexSignature.symbols @@ -0,0 +1,42 @@ +=== tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts === +interface Indexed { +>Indexed : Symbol(Indexed, Decl(objectSpreadIndexSignature.ts, 0, 0)) + + [n: string]: number; +>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 1, 5)) + + a: number; +>a : Symbol(Indexed.a, Decl(objectSpreadIndexSignature.ts, 1, 24)) +} +interface Indexed2 { +>Indexed2 : Symbol(Indexed2, Decl(objectSpreadIndexSignature.ts, 3, 1)) + + [n: string]: boolean; +>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 5, 5)) + + c: boolean; +>c : Symbol(Indexed2.c, Decl(objectSpreadIndexSignature.ts, 5, 25)) +} +let indexed: Indexed; +>indexed : Symbol(indexed, Decl(objectSpreadIndexSignature.ts, 8, 3)) +>Indexed : Symbol(Indexed, Decl(objectSpreadIndexSignature.ts, 0, 0)) + +let indexed2: Indexed2; +>indexed2 : Symbol(indexed2, Decl(objectSpreadIndexSignature.ts, 9, 3)) +>Indexed2 : Symbol(Indexed2, Decl(objectSpreadIndexSignature.ts, 3, 1)) + +let i = { ...indexed, b: 11 }; +>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 10, 3)) +>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 10, 21)) + +// only indexed has indexer, so i[101]: any +i[101]; +>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 10, 3)) + +let ii = { ...indexed, ...indexed2 }; +>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 13, 3)) + +// both have indexer, so i[1001]: number | boolean +ii[1001]; +>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 13, 3)) + diff --git a/tests/baselines/reference/objectSpreadIndexSignature.types b/tests/baselines/reference/objectSpreadIndexSignature.types new file mode 100644 index 00000000000..79a515e7374 --- /dev/null +++ b/tests/baselines/reference/objectSpreadIndexSignature.types @@ -0,0 +1,52 @@ +=== tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts === +interface Indexed { +>Indexed : Indexed + + [n: string]: number; +>n : string + + a: number; +>a : number +} +interface Indexed2 { +>Indexed2 : Indexed2 + + [n: string]: boolean; +>n : string + + c: boolean; +>c : boolean +} +let indexed: Indexed; +>indexed : Indexed +>Indexed : Indexed + +let indexed2: Indexed2; +>indexed2 : Indexed2 +>Indexed2 : Indexed2 + +let i = { ...indexed, b: 11 }; +>i : { b: number; a: number; } +>{ ...indexed, b: 11 } : { b: number; a: number; } +>indexed : any +>b : number +>11 : 11 + +// only indexed has indexer, so i[101]: any +i[101]; +>i[101] : any +>i : { b: number; a: number; } +>101 : 101 + +let ii = { ...indexed, ...indexed2 }; +>ii : { [x: string]: number | boolean; c: boolean; a: number; } +>{ ...indexed, ...indexed2 } : { [x: string]: number | boolean; c: boolean; a: number; } +>indexed : any +>indexed2 : any + +// both have indexer, so i[1001]: number | boolean +ii[1001]; +>ii[1001] : number | boolean +>ii : { [x: string]: number | boolean; c: boolean; a: number; } +>1001 : 1001 + diff --git a/tests/baselines/reference/objectSpreadNegative.errors.txt b/tests/baselines/reference/objectSpreadNegative.errors.txt index 1af94007dc1..dc6a356708f 100644 --- a/tests/baselines/reference/objectSpreadNegative.errors.txt +++ b/tests/baselines/reference/objectSpreadNegative.errors.txt @@ -1,30 +1,26 @@ -tests/cases/conformance/types/spread/objectSpreadNegative.ts(11,21): error TS2339: Property 'x' does not exist on type '{}'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(14,5): error TS2322: Type '{ sn?: string | number; }' is not assignable to type '{ sn: string | number; }'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(13,21): error TS2339: Property 'x' does not exist on type '{}'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(16,5): error TS2322: Type '{ sn?: string | number; }' is not assignable to type '{ sn: string | number; }'. Property 'sn' is optional in type '{ sn?: string | number; }' but required in type '{ sn: string | number; }'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(20,5): error TS2322: Type '{ s: string; }' is not assignable to type '{ s: string; b: boolean; }'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(23,1): error TS2322: Type '{ s: string; }' is not assignable to type '{ s: string; b: boolean; }'. Property 'b' is missing in type '{ s: string; }'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(22,1): error TS2322: Type 'Bool' is not assignable to type '{ s: string; b: boolean; }'. - Property 's' is missing in type 'Bool'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(25,36): error TS2300: Duplicate identifier 'b'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(25,53): error TS2300: Duplicate identifier 'b'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(30,12): error TS2339: Property 'null' does not exist on type '{}'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(32,17): error TS2339: Property 'undefined' does not exist on type '{}'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(36,11): error TS2339: Property 'toFixed' does not exist on type '{}'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(38,11): error TS2339: Property 'toFixed' does not exist on type '{}'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(40,11): error TS2339: Property 'length' does not exist on type '{}'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(41,11): error TS2339: Property 'charAt' does not exist on type '{}'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(45,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(49,12): error TS2339: Property 'b' does not exist on type '{}'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(55,9): error TS2339: Property 'm' does not exist on type '{ p: number; }'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(57,48): error TS2699: Type literals with spreads cannot contain index, call or construct signatures. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(57,69): error TS2699: Type literals with spreads cannot contain index, call or construct signatures. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(58,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ x: number; }' has no compatible call signatures. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(59,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(64,9): error TS2322: Type '{ ...T & V }' is not assignable to type '{ ...T & U }'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS2322: Type '{ ...U }' is not assignable to type 'U'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(25,1): error TS2322: Type '{ b: boolean; }' is not assignable to type '{ s: string; b: boolean; }'. + Property 's' is missing in type '{ b: boolean; }'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(28,36): error TS2300: Duplicate identifier 'b'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(28,53): error TS2300: Duplicate identifier 'b'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(32,20): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(33,24): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(34,19): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(35,19): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(37,20): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(39,19): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(44,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(48,12): error TS2339: Property 'b' does not exist on type '{}'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(54,9): error TS2339: Property 'm' does not exist on type '{ p: number; }'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(58,14): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(61,14): error TS2698: Spread types may only be created from object types. -==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (21 errors) ==== +==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (17 errors) ==== let o = { a: 1, b: 'no' } /// private propagates @@ -34,7 +30,9 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS232 class PublicX { public x: number; } - let o2: { ...PublicX, ...PrivateOptionalX }; + let publicX: PublicX; + let privateOptionalX: PrivateOptionalX; + let o2 = { ...publicX, ...privateOptionalX }; let sn: number = o2.x; // error, x is private ~ !!! error TS2339: Property 'x' does not exist on type '{}'. @@ -49,15 +47,16 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS232 // assignability as target interface Bool { b: boolean }; interface Str { s: string }; - let spread: { ...Bool, ...Str } = { s: 'foo' }; // error, missing 'b' - ~~~~~~ + let spread = { ...{ b: true }, ...{s: "foo" } }; + spread = { s: "foo" }; // error, missing 'b' + ~~~~~~ !!! error TS2322: Type '{ s: string; }' is not assignable to type '{ s: string; b: boolean; }'. !!! error TS2322: Property 'b' is missing in type '{ s: string; }'. - let b: Bool; + let b = { b: false }; spread = b; // error, missing 's' ~~~~~~ -!!! error TS2322: Type 'Bool' is not assignable to type '{ s: string; b: boolean; }'. -!!! error TS2322: Property 's' is missing in type 'Bool'. +!!! error TS2322: Type '{ b: boolean; }' is not assignable to type '{ s: string; b: boolean; }'. +!!! error TS2322: Property 's' is missing in type '{ b: boolean; }'. // literal repeats are not allowed, but spread repeats are fine let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' } @@ -67,34 +66,30 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS232 !!! error TS2300: Duplicate identifier 'b'. let duplicatedSpread = { ...o, ...o } - // null and undefined are just skipped - let spreadNull = { ...null } - spreadNull.null; - ~~~~ -!!! error TS2339: Property 'null' does not exist on type '{}'. - let spreadUndefined = { ...undefined } - spreadUndefined.undefined; - ~~~~~~~~~ -!!! error TS2339: Property 'undefined' does not exist on type '{}'. - - // primitives and functions are skipped + // null, undefined and primitives are not allowed + let spreadNull = { ...null }; + ~~~~~~~ +!!! error TS2698: Spread types may only be created from object types. + let spreadUndefind = { ...undefined }; + ~~~~~~~~~~~~ +!!! error TS2698: Spread types may only be created from object types. let spreadNum = { ...12 }; - spreadNum.toFixed(); // error, no methods from number - ~~~~~~~ -!!! error TS2339: Property 'toFixed' does not exist on type '{}'. + ~~~~~ +!!! error TS2698: Spread types may only be created from object types. let spreadSum = { ...1 + 1 }; + ~~~~~~~~ +!!! error TS2698: Spread types may only be created from object types. spreadSum.toFixed(); // error, no methods from number - ~~~~~~~ -!!! error TS2339: Property 'toFixed' does not exist on type '{}'. - let spreadStr = { ...'foo' }; - spreadStr.length; // error, no 'length' - ~~~~~~ -!!! error TS2339: Property 'length' does not exist on type '{}'. - spreadStr.charAt(1); // error, no methods either - ~~~~~~ -!!! error TS2339: Property 'charAt' does not exist on type '{}'. - let spreadBool = { ...true }; + let spreadBool = { ...false }; + ~~~~~~~~ +!!! error TS2698: Spread types may only be created from object types. spreadBool.valueOf(); // error, what were you thinking? + let spreadStr = { ...'foo' }; + ~~~~~~~~ +!!! error TS2698: Spread types may only be created from object types. + spreadStr.length; // error, no 'length' + spreadStr.charAt(1); // error, no methods either + // functions are skipped let spreadFunc = { ...function () { } } spreadFunc(); // error, no call signature ~~~~~~~~~~~~ @@ -114,27 +109,23 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS232 ~ !!! error TS2339: Property 'm' does not exist on type '{ p: number; }'. - let callableConstructableSpread: { ...PublicX, (n: number): number, new (p: number) }; - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2699: Type literals with spreads cannot contain index, call or construct signatures. - ~~~~~~~~~~~~~~~ -!!! error TS2699: Type literals with spreads cannot contain index, call or construct signatures. - callableConstructableSpread(12); // error, no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ x: number; }' has no compatible call signatures. - new callableConstructableSpread(12); // error, no construct signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. - - function override(initial: U, override: U, t: T, v: V): U { - // { ... T & V } is not assignable to { ... T & U } - let tvs: { ...T & V }; - let mistake: { ...T & U } = tvs; - ~~~~~~~ -!!! error TS2322: Type '{ ...T & V }' is not assignable to type '{ ...T & U }'. - // { ...U } is not assignable to U - return { ...initial, ...override }; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ ...U }' is not assignable to type 'U'. + // generics + function f(t: T, u: U) { + return { ...t, ...u, id: 'id' }; + ~~~~ +!!! error TS2698: Spread types may only be created from object types. } + function override(initial: U, override: U): U { + return { ...initial, ...override }; + ~~~~~~~~~~ +!!! error TS2698: Spread types may only be created from object types. + } + let exclusive: { id: string, a: number, b: string, c: string, d: boolean } = + f({ a: 1, b: 'yes' }, { c: 'no', d: false }) + let overlap: { id: string, a: number, b: string } = + f({ a: 1 }, { a: 2, b: 'extra' }) + let overlapConflict: { id:string, a: string } = + f({ a: 1 }, { a: 'mismatch' }) + let overwriteId: { id: string, a: number, c: number, d: string } = + f({ a: 1, id: true }, { c: 1, d: 'no' }) \ No newline at end of file diff --git a/tests/baselines/reference/objectSpreadNegative.js b/tests/baselines/reference/objectSpreadNegative.js index 7187b6009bd..4faacd97444 100644 --- a/tests/baselines/reference/objectSpreadNegative.js +++ b/tests/baselines/reference/objectSpreadNegative.js @@ -8,7 +8,9 @@ class PrivateOptionalX { class PublicX { public x: number; } -let o2: { ...PublicX, ...PrivateOptionalX }; +let publicX: PublicX; +let privateOptionalX: PrivateOptionalX; +let o2 = { ...publicX, ...privateOptionalX }; let sn: number = o2.x; // error, x is private let optionalString: { sn?: string }; let optionalNumber: { sn?: number }; @@ -18,30 +20,27 @@ let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumbe // assignability as target interface Bool { b: boolean }; interface Str { s: string }; -let spread: { ...Bool, ...Str } = { s: 'foo' }; // error, missing 'b' -let b: Bool; +let spread = { ...{ b: true }, ...{s: "foo" } }; +spread = { s: "foo" }; // error, missing 'b' +let b = { b: false }; spread = b; // error, missing 's' // literal repeats are not allowed, but spread repeats are fine let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' } let duplicatedSpread = { ...o, ...o } -// null and undefined are just skipped -let spreadNull = { ...null } -spreadNull.null; -let spreadUndefined = { ...undefined } -spreadUndefined.undefined; - -// primitives and functions are skipped +// null, undefined and primitives are not allowed +let spreadNull = { ...null }; +let spreadUndefind = { ...undefined }; let spreadNum = { ...12 }; -spreadNum.toFixed(); // error, no methods from number let spreadSum = { ...1 + 1 }; spreadSum.toFixed(); // error, no methods from number +let spreadBool = { ...false }; +spreadBool.valueOf(); // error, what were you thinking? let spreadStr = { ...'foo' }; spreadStr.length; // error, no 'length' spreadStr.charAt(1); // error, no methods either -let spreadBool = { ...true }; -spreadBool.valueOf(); // error, what were you thinking? +// functions are skipped let spreadFunc = { ...function () { } } spreadFunc(); // error, no call signature @@ -55,17 +54,21 @@ let c: C = new C() let spreadC = { ...c } spreadC.m(); // error 'm' is not in '{ ... c }' -let callableConstructableSpread: { ...PublicX, (n: number): number, new (p: number) }; -callableConstructableSpread(12); // error, no call signature -new callableConstructableSpread(12); // error, no construct signature - -function override(initial: U, override: U, t: T, v: V): U { - // { ... T & V } is not assignable to { ... T & U } - let tvs: { ...T & V }; - let mistake: { ...T & U } = tvs; - // { ...U } is not assignable to U +// generics +function f(t: T, u: U) { + return { ...t, ...u, id: 'id' }; +} +function override(initial: U, override: U): U { return { ...initial, ...override }; } +let exclusive: { id: string, a: number, b: string, c: string, d: boolean } = + f({ a: 1, b: 'yes' }, { c: 'no', d: false }) +let overlap: { id: string, a: number, b: string } = + f({ a: 1 }, { a: 2, b: 'extra' }) +let overlapConflict: { id:string, a: string } = + f({ a: 1 }, { a: 'mismatch' }) +let overwriteId: { id: string, a: number, c: number, d: string } = + f({ a: 1, id: true }, { c: 1, d: 'no' }) //// [objectSpreadNegative.js] @@ -89,34 +92,34 @@ var PublicX = (function () { } return PublicX; }()); -var o2; +var publicX; +var privateOptionalX; +var o2 = __assign({}, publicX, privateOptionalX); var sn = o2.x; // error, x is private var optionalString; var optionalNumber; var allOptional = __assign({}, optionalString, optionalNumber); ; ; -var spread = { s: 'foo' }; // error, missing 'b' -var b; +var spread = __assign({ b: true }, { s: "foo" }); +spread = { s: "foo" }; // error, missing 'b' +var b = { b: false }; spread = b; // error, missing 's' // literal repeats are not allowed, but spread repeats are fine var duplicated = __assign({ b: 'bad' }, o, { b: 'bad' }, o2, { b: 'bad' }); var duplicatedSpread = __assign({}, o, o); -// null and undefined are just skipped +// null, undefined and primitives are not allowed var spreadNull = __assign({}, null); -spreadNull.null; -var spreadUndefined = __assign({}, undefined); -spreadUndefined.undefined; -// primitives and functions are skipped +var spreadUndefind = __assign({}, undefined); var spreadNum = __assign({}, 12); -spreadNum.toFixed(); // error, no methods from number var spreadSum = __assign({}, 1 + 1); spreadSum.toFixed(); // error, no methods from number +var spreadBool = __assign({}, false); +spreadBool.valueOf(); // error, what were you thinking? var spreadStr = __assign({}, 'foo'); spreadStr.length; // error, no 'length' spreadStr.charAt(1); // error, no methods either -var spreadBool = __assign({}, true); -spreadBool.valueOf(); // error, what were you thinking? +// functions are skipped var spreadFunc = __assign({}, function () { }); spreadFunc(); // error, no call signature // write-only properties get skipped @@ -133,13 +136,14 @@ var C = (function () { var c = new C(); var spreadC = __assign({}, c); spreadC.m(); // error 'm' is not in '{ ... c }' -var callableConstructableSpread; -callableConstructableSpread(12); // error, no call signature -new callableConstructableSpread(12); // error, no construct signature -function override(initial, override, t, v) { - // { ... T & V } is not assignable to { ... T & U } - var tvs; - var mistake = tvs; - // { ...U } is not assignable to U +// generics +function f(t, u) { + return __assign({}, t, u, { id: 'id' }); +} +function override(initial, override) { return __assign({}, initial, override); } +var exclusive = f({ a: 1, b: 'yes' }, { c: 'no', d: false }); +var overlap = f({ a: 1 }, { a: 2, b: 'extra' }); +var overlapConflict = f({ a: 1 }, { a: 'mismatch' }); +var overwriteId = f({ a: 1, id: true }, { c: 1, d: 'no' }); diff --git a/tests/baselines/reference/objectSpreadNegativeParse.errors.txt b/tests/baselines/reference/objectSpreadNegativeParse.errors.txt index 41651fb1d1c..987172ef867 100644 --- a/tests/baselines/reference/objectSpreadNegativeParse.errors.txt +++ b/tests/baselines/reference/objectSpreadNegativeParse.errors.txt @@ -1,26 +1,36 @@ +tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,12): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,15): error TS2304: Cannot find name 'o'. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,18): error TS1109: Expression expected. +tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,12): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,15): error TS1109: Expression expected. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,16): error TS2304: Cannot find name 'o'. +tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,12): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,15): error TS2304: Cannot find name 'matchMedia'. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,28): error TS1005: ',' expected. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,31): error TS1128: Declaration or statement expected. +tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,13): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,16): error TS2304: Cannot find name 'get'. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,20): error TS1005: ',' expected. -==== tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts (9 errors) ==== +==== tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts (13 errors) ==== let o7 = { ...o? }; + ~~~~~ +!!! error TS2698: Spread types may only be created from object types. ~ !!! error TS2304: Cannot find name 'o'. ~ !!! error TS1109: Expression expected. let o8 = { ...*o }; + ~~~~~ +!!! error TS2698: Spread types may only be created from object types. ~ !!! error TS1109: Expression expected. ~ !!! error TS2304: Cannot find name 'o'. let o9 = { ...matchMedia() { }}; + ~~~~~~~~~~~~~~~ +!!! error TS2698: Spread types may only be created from object types. ~~~~~~~~~~ !!! error TS2304: Cannot find name 'matchMedia'. ~ @@ -28,6 +38,8 @@ tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,20): error T ~ !!! error TS1128: Declaration or statement expected. let o10 = { ...get x() { return 12; }}; + ~~~~~~ +!!! error TS2698: Spread types may only be created from object types. ~~~ !!! error TS2304: Cannot find name 'get'. ~ diff --git a/tests/cases/conformance/types/spread/interfaceSpread.ts b/tests/cases/conformance/types/spread/interfaceSpread.ts deleted file mode 100644 index a92a188e1a8..00000000000 --- a/tests/cases/conformance/types/spread/interfaceSpread.ts +++ /dev/null @@ -1,8 +0,0 @@ -interface Congealed { - ...T - ...U -} - -let sandwich: Congealed<{jam: number }, { peanutButter: number }>; -sandwich.jam; -sandwich.peanutButter; diff --git a/tests/cases/conformance/types/spread/objectSpread.ts b/tests/cases/conformance/types/spread/objectSpread.ts index daadb1e3270..3336196e136 100644 --- a/tests/cases/conformance/types/spread/objectSpread.ts +++ b/tests/cases/conformance/types/spread/objectSpread.ts @@ -35,13 +35,8 @@ let getter: { a: number, c: number } = { ...op, c: 7 } getter.a = 12; -// null, undefined, functions and primitives result in { } -let spreadNull = { ...null }; -let spreadUndefind = { ...undefined }; -let spreadNum = { ...12 }; -let spreadBool = { ...false }; +// functions result in { } let spreadFunc = { ...(function () { }) }; -let spreadStr = { ...'foo' }; // methods are not enumerable class C { p = 1; m() { } } @@ -80,19 +75,3 @@ let computedAfter: { a: number, b: string, "at the end": number } = let a = 12; let shortCutted: { a: number, b: string } = { ...o, a } -// generics -function f(t: T, u: U): { ...T, ...U, id: string } { - return { ...t, ...u, id: 'id' }; -} -let exclusive: { id: string, a: number, b: string, c: string, d: boolean } = - f({ a: 1, b: 'yes' }, { c: 'no', d: false }) -let overlap: { id: string, a: number, b: string } = - f({ a: 1 }, { a: 2, b: 'extra' }) -let overlapConflict: { id:string, a: string } = - f({ a: 1 }, { a: 'mismatch' }) -let overwriteId: { id: string, a: number, c: number, d: string } = - f({ a: 1, id: true }, { c: 1, d: 'no' }) - -class D { m() { }; q = 2; } -let classesAreWrong: { id: string, ...C, ...D } = - f(new C(), new D()) diff --git a/tests/cases/conformance/types/spread/objectSpreadGeneric.ts b/tests/cases/conformance/types/spread/objectSpreadGeneric.ts deleted file mode 100644 index 6f22358b7e2..00000000000 --- a/tests/cases/conformance/types/spread/objectSpreadGeneric.ts +++ /dev/null @@ -1,72 +0,0 @@ -function f(t: T, u: U, v: V): void { - let o: { ...T, ...U, ...V }; - let uus: { ...U, ...U}; - let us: { ...U }; - const same: { ...T, ...U, ...V } = o; // ok - uus = us; // ok, multiple spreads are equivalent to a single one - us = uus; // ok, multiple spreads are equivalent to a single one - us = u; // ok, type has at least all the properties of the spread - u = us; // error, might be missing a ton of stuff - const reversed: { ...V, ...U, ...T } = o; // error, reversed - const reversed2: { ...U, ...T, ...V } = o; // error, U and T are still reversed - const missingT: { ...U, ...V } = o; // error, missing T - const missingU: { ...T, ...V } = o; // error, missing U - const missingV: { ...T, ...U } = o; // error, missing V - const atEnd: { ...T, ...U, second: string } = { ...t, ...u, second: 'foo' }; // ok - const atBeginning: { first: string, ...T, ...U, } = { first: 'foo', ...t, ...u }; // error, not assignable - - const emptyTarget: { } = { ...t, ...u } // ok - const emptySource: { ...T, ...U } = { }; // error, {} is not assignable to U (or T) - - // error, { sn?: boolean } ...T ... { sn?: number | string } is not assignable to - // T ... { sn?: number | string | boolean } - let optionalNumber: { sn?: number }; - let optionalString: { sn?: string }; - let optionalBoolean: { sn?: boolean }; - const unionCutoff: { ...T, sn?: number | string | boolean } = - { ...optionalBoolean, ...t, ...optionalString, ...optionalNumber } - unionCutoff.sn; // ok - const optionalCutoff = { ...t, ...optionalNumber }; // ok - optionalCutoff.sn; // ok - - const interspersed: { first: string, ...T, second: string, ...U, third: string } = - { first: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable - const interspersedMissingU: { first: string, second: string, ...T, third: string } = - { first: '1', ...t, second: '2', ...u, third: '3' }; // error, 'U' is missing - const interspersedOrder1: { first: string, ...T, second: string, ...U, third: string, secondsecond: string } = - { first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable - const interspersedOrder2: { first: string, second: string, secondsecond: string, third: string, ...T, ...U } = - { first: '1', ...t, second: '2', ...u, third: '3', secondsecond: 'false' }; // error, not assignable - - - const mismatchFirst: { first: string, ...T, second: string, ...U, third: string } = - { firrrrrrst: '1', ...t, second: '2', ...u, third: '3' }; // error, not assignable - const mismatchSecond: { first: string, ...T, second: string, ...U, third: string } = - { first: '1', ...t, ssssssssecond: '2', ...u, third: '3' }; // error, not assignable - const mismatchLast: { first: string, ...T, second: string, ...U, third: string } = - { first: '1', ...t, second: '2', ...u, thirrrrrrrd: '3' }; // error, not assignable -} - -function indexAccessedTest(t: T, u: U, key1: K, key2: J) { - let k1: { ...keyof T }; - let k2: { ...keyof U }; - let k3: { ...K }; - let k4: { ...J }; - k1 = k1; // ok - k2 = k2; // ok - k1 = k2; // error - k2 = k1; // error - k3 = k3; // ok - k4 = k4; // ok - k1 = k3; // error - k3 = k1; // error - k2 = k4; // error - k4 = k2; // error - - let i1: { ...T[K] }; - let i2: { ...U[J] }; - i1 = i1; // ok - i2 = i2; // ok - i1 = i2; // error - i2 = i1; // error -} diff --git a/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts b/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts index 8c9194d2d4c..ae46f2547d5 100644 --- a/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts +++ b/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts @@ -1,25 +1,16 @@ -class C { - a: number; - c: boolean; -} -// index signatures are not allowed in object literals with spread types -let c: { ...C, b: string, c?: string, [n: number]: string }; -let n: number = c.a; -let s: string = c[12]; interface Indexed { [n: string]: number; a: number; } -let i: { ...Indexed, b: number }; -n = i[101]; -n = i.b; interface Indexed2 { [n: string]: boolean; c: boolean; } -let ii: { ...Indexed, ...Indexed2, b: boolean, d: number }; -let nb: number | boolean = ii[1001]; - -function f(t: T) { - let i: { ...T, [n: number]: string }; -} +let indexed: Indexed; +let indexed2: Indexed2; +let i = { ...indexed, b: 11 }; +// only indexed has indexer, so i[101]: any +i[101]; +let ii = { ...indexed, ...indexed2 }; +// both have indexer, so i[1001]: number | boolean +ii[1001]; diff --git a/tests/cases/conformance/types/spread/objectSpreadInference.ts b/tests/cases/conformance/types/spread/objectSpreadInference.ts deleted file mode 100644 index 9608f0a16cb..00000000000 --- a/tests/cases/conformance/types/spread/objectSpreadInference.ts +++ /dev/null @@ -1,19 +0,0 @@ -interface Result { - t: T; - u: U; - v: V; -} -declare function infer(tuv: { ...T, ...U, a: V }): { t: T, u: U, v: V }; -declare function infer2(utv: { ...U, a: V, ...T }): { t: T, u: U, v: V }; -function generic(w: W, x: X, y: Y) { - // should infer { t: {}, u: {}, v: {} } because there is no trailing type parameter - return infer({ ...w, ...x, a: y, b: "different type" }); -} -let b: { b: number }; -let c: { c: number }; -// can only infer { t: {}, u: {}, v: {} } -let i1 = infer({ ...b, ...c, a: 12 }); -// can only infer { t: {}, u: {}, v: {} } -let i2 = infer2({ ...b, ...c, a: 12 }); -// can only infer { t: {}, u: {}, v: {} } -let i3 = generic(b, c, { a: 12 }); diff --git a/tests/cases/conformance/types/spread/objectSpreadIntersection.ts b/tests/cases/conformance/types/spread/objectSpreadIntersection.ts deleted file mode 100644 index 3bedacca89f..00000000000 --- a/tests/cases/conformance/types/spread/objectSpreadIntersection.ts +++ /dev/null @@ -1,36 +0,0 @@ -function iteratedUnionIntersection(t: T, u: U, v: V): void { - let tu: T | U; - let uv: U & V; - let result = { ...tu, ...uv, id: 'foo' }; - let assignable: { ...(T | U), ...(U & V), id: string } = result; -} -// concrete types work -interface A1 { a: number } -interface A2 { a: string } -interface B1 { b: number } -interface B2 { b: string } -let a12: A1 & A2; -let b12: B1 & B2; -let result = { ...a12, ...b12 }; -let sn: number & string = result.a; -sn = result.b; -let assignable: { ...(A1 & A2), ...(B1 & B2) } = result; - -function tripleIntersection(t: T, u: U, v: V): void { - let tuv: T & U & V; - let result = { ...tuv, id: 'bar' }; - let assignable: { ...(T & U & V), id: string } = result; -} -function iteratedDoubleIntersection(t: T, u: U, v: V): void { - let tu: T & U; - let uv: U & V; - let result = { ...tu, ...uv, id: 'baz' }; - let assignable: { ...(T & U), ...(U & V), id: string } = result; -} -function iteratedIntersectionUnion(t: T, u: U, v: V): void { - let tu: T & U; - let uv: U | V; - let result = { ...tu, ...uv, id: 'qux' }; - let assignable: { ...(T & U), ...(U | V), id: string } = result; -} - diff --git a/tests/cases/conformance/types/spread/objectSpreadNegative.ts b/tests/cases/conformance/types/spread/objectSpreadNegative.ts index 146ab072bbf..3cd819d0613 100644 --- a/tests/cases/conformance/types/spread/objectSpreadNegative.ts +++ b/tests/cases/conformance/types/spread/objectSpreadNegative.ts @@ -8,7 +8,9 @@ class PrivateOptionalX { class PublicX { public x: number; } -let o2: { ...PublicX, ...PrivateOptionalX }; +let publicX: PublicX; +let privateOptionalX: PrivateOptionalX; +let o2 = { ...publicX, ...privateOptionalX }; let sn: number = o2.x; // error, x is private let optionalString: { sn?: string }; let optionalNumber: { sn?: number }; @@ -18,30 +20,27 @@ let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumbe // assignability as target interface Bool { b: boolean }; interface Str { s: string }; -let spread: { ...Bool, ...Str } = { s: 'foo' }; // error, missing 'b' -let b: Bool; +let spread = { ...{ b: true }, ...{s: "foo" } }; +spread = { s: "foo" }; // error, missing 'b' +let b = { b: false }; spread = b; // error, missing 's' // literal repeats are not allowed, but spread repeats are fine let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' } let duplicatedSpread = { ...o, ...o } -// null and undefined are just skipped -let spreadNull = { ...null } -spreadNull.null; -let spreadUndefined = { ...undefined } -spreadUndefined.undefined; - -// primitives and functions are skipped +// null, undefined and primitives are not allowed +let spreadNull = { ...null }; +let spreadUndefind = { ...undefined }; let spreadNum = { ...12 }; -spreadNum.toFixed(); // error, no methods from number let spreadSum = { ...1 + 1 }; spreadSum.toFixed(); // error, no methods from number +let spreadBool = { ...false }; +spreadBool.valueOf(); // error, what were you thinking? let spreadStr = { ...'foo' }; spreadStr.length; // error, no 'length' spreadStr.charAt(1); // error, no methods either -let spreadBool = { ...true }; -spreadBool.valueOf(); // error, what were you thinking? +// functions are skipped let spreadFunc = { ...function () { } } spreadFunc(); // error, no call signature @@ -55,14 +54,18 @@ let c: C = new C() let spreadC = { ...c } spreadC.m(); // error 'm' is not in '{ ... c }' -let callableConstructableSpread: { ...PublicX, (n: number): number, new (p: number) }; -callableConstructableSpread(12); // error, no call signature -new callableConstructableSpread(12); // error, no construct signature - -function override(initial: U, override: U, t: T, v: V): U { - // { ... T & V } is not assignable to { ... T & U } - let tvs: { ...T & V }; - let mistake: { ...T & U } = tvs; - // { ...U } is not assignable to U +// generics +function f(t: T, u: U) { + return { ...t, ...u, id: 'id' }; +} +function override(initial: U, override: U): U { return { ...initial, ...override }; } +let exclusive: { id: string, a: number, b: string, c: string, d: boolean } = + f({ a: 1, b: 'yes' }, { c: 'no', d: false }) +let overlap: { id: string, a: number, b: string } = + f({ a: 1 }, { a: 2, b: 'extra' }) +let overlapConflict: { id:string, a: string } = + f({ a: 1 }, { a: 'mismatch' }) +let overwriteId: { id: string, a: number, c: number, d: string } = + f({ a: 1, id: true }, { c: 1, d: 'no' }) diff --git a/tests/cases/conformance/types/spread/objectSpreadScenarios.ts b/tests/cases/conformance/types/spread/objectSpreadScenarios.ts deleted file mode 100644 index 1db930cb71c..00000000000 --- a/tests/cases/conformance/types/spread/objectSpreadScenarios.ts +++ /dev/null @@ -1,17 +0,0 @@ -interface A1 { a: boolean } -interface B1 { b: number }; -function override(initial: U, override: U): { ...U, ...U } { - return { ...initial, ...override }; -} -function update(this: { u: { ...U } }, override: U): void { - this.u = { ...this.u, ...override }; -} -function mixin(one: T, two: U): { ...T, ...U } { - return { ...one, ...two }; -} -let a1: A1 = { a: true }; -let b1: B1 = { b: 101 }; -a1 = override(a1, { a: false }); -let host = { u: a1, update }; -host.update({ a: false }); -let mixed = mixin(a1, b1); diff --git a/tests/cases/conformance/types/spread/objectSpreadUnion.ts b/tests/cases/conformance/types/spread/objectSpreadUnion.ts deleted file mode 100644 index cd490d76bda..00000000000 --- a/tests/cases/conformance/types/spread/objectSpreadUnion.ts +++ /dev/null @@ -1,23 +0,0 @@ -// concrete types work -interface A1 { a: number } -interface A2 { a: string } -let a12: A1 | A2; -let result = { ...a12 }; -let sn: number | string = result.a; -let assignable: { ...(A1 | A2) } = result; - -function tripleUnion(t: T, u: U, v: V): void { - let tuv: T | U | V; - let result = { ...tuv, id: 'foo' }; - let expected: { ...T, id: string } | { ...U, id: string } | { ...V, id: string } = result; - let assignable: { ...(T | U | V), id: string } = result; -} -function iteratedDoubleUnion(t: T, u: U, v: V): void { - let tu: T | U; - let uv: U | V; - let result = { ...tu, ...uv, id: 'bar' }; - let expected: { ...T, ...U, id: string } | { ...T, ...V, id: string } | { ...U, id: string } | { ...U, ...V, id: string }; - let assignable: { ...(T | U), ...(U | V), id: string } = result; -} - - diff --git a/tests/cases/fourslash/findAllRefsForObjectSpread.ts b/tests/cases/fourslash/findAllRefsForObjectSpread.ts index 650324a5d84..05c83491f66 100644 --- a/tests/cases/fourslash/findAllRefsForObjectSpread.ts +++ b/tests/cases/fourslash/findAllRefsForObjectSpread.ts @@ -2,7 +2,9 @@ ////interface A1 { [|a|]: string }; ////interface A2 { [|a|]?: number }; -////let a12: { ...A1, ...A2 }; +////let a1: A1; +////let a2: A2; +////let a12 = { ...a1, ...a2 }; ////a12.[|a|]; const ranges = test.ranges(); // members of spread types only refer to themselves and the resulting property diff --git a/tests/cases/fourslash/goToDefinitionObjectSpread.ts b/tests/cases/fourslash/goToDefinitionObjectSpread.ts index 64623c36cb7..b23d0a80448 100644 --- a/tests/cases/fourslash/goToDefinitionObjectSpread.ts +++ b/tests/cases/fourslash/goToDefinitionObjectSpread.ts @@ -2,6 +2,8 @@ ////interface A1 { /*1*/a: number }; ////interface A2 { /*2*/a?: number }; -////let a12: { ...A1, ...A2 }; +////let a1: A1; +////let a2: A2; +////let a12 = { ...a1, ...a2 }; ////a12.a/*3*/; verify.goToDefinition('3', [ '1', '2' ]); diff --git a/tests/cases/fourslash/renameObjectSpread.ts b/tests/cases/fourslash/renameObjectSpread.ts index a2c640361e5..eba148c0e39 100644 --- a/tests/cases/fourslash/renameObjectSpread.ts +++ b/tests/cases/fourslash/renameObjectSpread.ts @@ -2,7 +2,9 @@ ////interface A1 { [|a|]: number }; ////interface A2 { [|a|]?: number }; -////let a12: { ...A1, ...A2 }; +////let a1: A1; +////let a2: A2; +////let a12 = { ...a1, ...a2 }; ////a12.[|a|]; const ranges = test.ranges(); verify.assertHasRanges(ranges); From 7a2c7ad37420ad8f11652a6b87116c1b20fca802 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 3 Nov 2016 09:41:31 -0700 Subject: [PATCH 4/4] Spread handles index signatures from singleton spreads I broke it when simplifying the logic earlier. --- src/compiler/checker.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 872aad6b046..3475a9d52c6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5888,8 +5888,17 @@ namespace ts { Debug.assert(!!(left.flags & TypeFlags.Object) && !!(right.flags & TypeFlags.Object), "Only object types may be spread."); const members = createMap(); const skippedPrivateMembers = createMap(); - const stringIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.String), getIndexInfoOfType(right, IndexKind.String)); - const numberIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.Number), getIndexInfoOfType(right, IndexKind.Number)); + let stringIndexInfo: IndexInfo; + let numberIndexInfo: IndexInfo; + if (left === emptyObjectType) { + // for the first spread element, left === emptyObjectType, so take the right's string indexer + stringIndexInfo = getIndexInfoOfType(right, IndexKind.String); + numberIndexInfo = getIndexInfoOfType(right, IndexKind.Number); + } + else { + stringIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.String), getIndexInfoOfType(right, IndexKind.String)); + numberIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, IndexKind.Number), getIndexInfoOfType(right, IndexKind.Number)); + } const isFromSpread = right.symbol !== symbol; for (const rightProp of getPropertiesOfType(right)) {