From c2562b43ddb2e3df01b8892302579e3d26dace6f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 4 Jan 2017 14:32:03 -0800 Subject: [PATCH 1/9] Spread types --- src/compiler/checker.ts | 282 ++++++++++++++++++++++++++- src/compiler/declarationEmitter.ts | 9 + src/compiler/diagnosticMessages.json | 8 + src/compiler/parser.ts | 29 ++- src/compiler/types.ts | 22 ++- 5 files changed, 334 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3b88122b028ed..e59751c434869 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -124,6 +124,7 @@ namespace ts { const tupleTypes: GenericType[] = []; const unionTypes = createMap(); const intersectionTypes = createMap(); + const spreadTypes = createMap(); const stringLiteralTypes = createMap(); const numericLiteralTypes = createMap(); const indexedAccessTypes = createMap(); @@ -2319,6 +2320,9 @@ namespace ts { else if (type.flags & TypeFlags.UnionOrIntersection) { writeUnionOrIntersectionType(type, nextFlags); } + else if (type.flags & TypeFlags.Spread) { + writeSpreadType(type as SpreadType); + } else if (getObjectFlags(type) & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) { writeAnonymousType(type, nextFlags); } @@ -2434,6 +2438,48 @@ namespace ts { } } + function writeSpreadType(type: SpreadType) { + writePunctuation(writer, SyntaxKind.OpenBraceToken); + writer.writeLine(); + writer.increaseIndent(); + + writeSpreadTypeWorker(type, /*atEnd*/true); + + writer.decreaseIndent(); + writePunctuation(writer, SyntaxKind.CloseBraceToken); + } + + function writeSpreadTypeWorker(type: SpreadType, atEnd: boolean): void { + if (type.left.flags & TypeFlags.Spread) { + writeSpreadTypeWorker(type.left as SpreadType, /*atEnd*/false); + } + else { + const saveInObjectTypeLiteral = inObjectTypeLiteral; + inObjectTypeLiteral = true; + writeObjectLiteralType(resolveStructuredTypeMembers(type.left as ResolvedType)); + inObjectTypeLiteral = saveInObjectTypeLiteral; + } + if (type.right.flags & TypeFlags.Object) { + // if type.right is an object 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) { @@ -4769,13 +4815,19 @@ 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 * type itself. Note that the apparent type of a union type is the union type itself. */ function getApparentType(type: Type): Type { - const t = type.flags & TypeFlags.TypeVariable ? getApparentTypeOfTypeVariable(type) : type; + const t = type.flags & TypeFlags.TypeVariable ? getApparentTypeOfTypeVariable(type) : + type.flags & TypeFlags.Spread ? getApparentTypeOfSpread(type as SpreadType) : + type; return t.flags & TypeFlags.StringLike ? globalStringType : t.flags & TypeFlags.NumberLike ? globalNumberType : t.flags & TypeFlags.BooleanLike ? globalBooleanType : @@ -6209,6 +6261,12 @@ namespace ts { function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: TypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { + const hasSpread = (node.kind === SyntaxKind.TypeLiteral && + find((node as TypeLiteralNode).members, elt => elt.kind === SyntaxKind.SpreadTypeAssignment)); + if (hasSpread) { + return getTypeFromSpreadTypeLiteral(node as TypeLiteralNode); + } + // Deferred resolution of members is handled by resolveObjectTypeMembers const aliasSymbol = getAliasSymbolForTypeNode(node); if (isEmpty(node.symbol.members) && !aliasSymbol) { @@ -6224,6 +6282,50 @@ namespace ts { return links.resolvedType; } + function getTypeFromSpreadTypeLiteral(node: TypeLiteralNode): Type { + let spread: Type = emptyObjectType; + let members: Map; + let stringIndexInfo: IndexInfo; + let numberIndexInfo: IndexInfo; + for (const member of node.members) { + if (member.kind === SyntaxKind.SpreadTypeAssignment) { + if (members) { + const type = createAnonymousType(node.symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); + spread = getSpreadType(spread, type, /*isFromObjectLiteral*/ true); + members = undefined; + stringIndexInfo = undefined; + numberIndexInfo = undefined; + } + const type = getTypeFromTypeNode((member as SpreadTypeAssignment).type); + spread = getSpreadType(spread, type, /*isFromObjectLiteral*/ false); + } + 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 = getTypeFromTypeNode((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, /*isFromObjectLiteral*/ true); + } + if (spread.flags & TypeFlags.Object) { + // only set the symbol if this is a (fresh) object type + spread.symbol = node.symbol; + } + return spread; + } + function getAliasSymbolForTypeNode(node: TypeNode) { return node.parent.kind === SyntaxKind.TypeAliasDeclaration ? getSymbolOfNode(node.parent) : undefined; } @@ -6237,11 +6339,32 @@ namespace ts { * Since the source of spread types are object 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. + * + * If getSpreadType returns a spread type, the following properties hold: + * 1. Left-deep: spread.left is always another spread type (the recursive case) + or an object (the terminal case) + * Callers of getSpreadType should use emptyObjectType as the initial object + if the left-most type is not an object. + * 2. spread.right is never a spread type, but one of + TypeParameter, Object, Intersection, Index or IndexedAccess + * 3. When recurring down a spread type chain, you will never encounter two object types in a row. */ - function getSpreadType(left: Type, right: Type, isFromObjectLiteral: boolean): Type { + function getSpreadType(left: Type, right: Type, isFromObjectLiteral: boolean): Type { if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } + const id = getTypeListId([left, right]); + if (id in spreadTypes) { + return spreadTypes[id]; + } + // 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); + } + // filter null and undefined left = filterType(left, t => !(t.flags & TypeFlags.Nullable)); if (left.flags & TypeFlags.Never) { return right; @@ -6250,13 +6373,92 @@ namespace ts { if (right.flags & TypeFlags.Never) { return left; } + // distribute union over spread if (left.flags & TypeFlags.Union) { return mapType(left, t => getSpreadType(t, right, isFromObjectLiteral)); } if (right.flags & TypeFlags.Union) { return mapType(right, t => getSpreadType(left, t, isFromObjectLiteral)); } + // filter primitives (this will be an error later) + if (left.flags & TypeFlags.Primitive && right.flags & TypeFlags.Primitive) { + return emptyObjectType; + } + if (left.flags & TypeFlags.Primitive) { + return right; + } + if (right.flags & TypeFlags.Primitive) { + return left; + } + + const simplified = simplifySpreadType(left, right, isFromObjectLiteral); + if (simplified) { + return simplified; + } + if (right.flags & TypeFlags.Object && left.flags & TypeFlags.Object) { + return createSpreadType(left, right, isFromObjectLiteral); + } + 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.left = left as SpreadType | ResolvedType; + spread.right = right as TypeParameter | IntersectionType | IndexType | IndexedAccessType | ResolvedType; + return spread; + } + + function resolveObjectIntersection(intersection: IntersectionType): IntersectionType | ResolvedType { + if (find(intersection.types, t => !(t.flags & TypeFlags.Object))) { + return intersection; + } + const members = createMap(); + for (const property of getPropertiesOfType(intersection)) { + members[property.name] = property; + } + const stringIndex = getIndexInfoOfType(intersection, IndexKind.String); + const numberIndex = getIndexInfoOfType(intersection, IndexKind.Number); + return createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndex, numberIndex); + } + + /** + * Simplify spread types: + * 1. Collapse duplicates: T ... T => T + * 2. Collapse adjacent object types: { x } ... { y } ... T => { x, y } ... T + * 3. Associativity: (T ... U) .. V => T ... (U ... V) + * + * (2) and (3) are important for creating a spread type that obeys the invariants described + * in getSpreadType. + */ + function simplifySpreadType(left: Type, right: Type, isFromObjectLiteral: boolean) { + if (left.flags & TypeFlags.Spread && + right.flags & TypeFlags.TypeParameter && + (left as SpreadType).right.flags & TypeFlags.TypeParameter && + right.symbol === (left as SpreadType).right.symbol) { + // ... T ... T => ... 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 } => T ... { x, y } + const simplified = getSpreadType(right, (left as SpreadType).right, isFromObjectLiteral); + return getSpreadType((left as SpreadType).left, simplified, isFromObjectLiteral); + } + if (right.flags & TypeFlags.Spread) { + // spread is right associated and associativity applies, so + // (T ... U) ... V => T ... (U ... V) + const rspread = right as SpreadType; + if (rspread.left === emptyObjectType) { + // ... U ... ({} ... T) => ... U ... T + return getSpreadType(left, rspread.right, isFromObjectLiteral); + } + return getSpreadType(getSpreadType(left, rspread.left, isFromObjectLiteral), + rspread.right, + isFromObjectLiteral); + } + } + + function createSpreadType(left: Type, right: Type, isFromObjectLiteral: boolean) { const members = createMap(); const skippedPrivateMembers = createMap(); let stringIndexInfo: IndexInfo; @@ -6811,6 +7013,10 @@ namespace ts { if (type.flags & TypeFlags.Intersection) { return getIntersectionType(instantiateTypes((type).types, mapper), type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)); } + if (type.flags & TypeFlags.Spread) { + const spread = type as SpreadType; + return getSpreadType(instantiateType(spread.left, mapper), instantiateType(spread.right, mapper), /*isFromObjectLiteral*/ false); + } if (type.flags & TypeFlags.Index) { return getIndexType(instantiateType((type).type, mapper)); } @@ -7443,6 +7649,20 @@ namespace ts { } } } + else if (source.flags & TypeFlags.Spread && target.flags & TypeFlags.Spread) { + 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) { // A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X. @@ -7454,6 +7674,13 @@ namespace ts { return result; } } + else 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; + } + } else { let constraint = getConstraintOfTypeParameter(source); @@ -7517,6 +7744,32 @@ 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) { @@ -11656,7 +11909,7 @@ namespace ts { typeFlags = 0; } const type = checkExpression((memberDecl as SpreadAssignment).expression); - if (!isValidSpreadType(type)) { + if (type.flags & (TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.BooleanLike | TypeFlags.EnumLike | TypeFlags.ESSymbol)) { error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types); return unknownType; } @@ -15989,10 +16242,19 @@ namespace ts { function checkTypeLiteral(node: TypeLiteralNode) { forEach(node.members, checkSourceElement); if (produceDiagnostics) { - const type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); - checkIndexConstraints(type); - checkTypeForDuplicateIndexSignatures(node); - checkObjectTypeForDuplicateDeclarations(node); + if (find(node.members, p => p.kind === SyntaxKind.SpreadTypeAssignment)) { + 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_constructor_signatures); + } + } + else { + const type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); + checkIndexConstraints(type); + checkTypeForDuplicateIndexSignatures(node); + checkObjectTypeForDuplicateDeclarations(node); + } } } @@ -21362,6 +21624,12 @@ namespace ts { checkGrammarHeritageClause(heritageClause); } } + + let result: TypeElement; + if (result = find(node.members, e => e.kind === SyntaxKind.SpreadTypeAssignment)) { + 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 cd98622e080a1..b023d33c9717a 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1174,6 +1174,13 @@ namespace ts { writeLine(); } + function emitSpreadTypeAssignment(type: SpreadTypeAssignment) { + 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 @@ -1764,6 +1771,8 @@ namespace ts { case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: return emitPropertyDeclaration(node); + case SyntaxKind.SpreadTypeAssignment: + return emitSpreadTypeAssignment(node as SpreadTypeAssignment); case SyntaxKind.EnumMember: return emitEnumMemberDeclaration(node); case SyntaxKind.ExportAssignment: diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ec5ca292b99ae..946c073cb55ba 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2015,6 +2015,10 @@ "category": "Error", "code": 2698 }, + "Type literals with spreads cannot contain index, call or constructor signatures.": { + "category": "Error", + "code": 2699 + }, "Rest types may only be created from object types.": { "category": "Error", "code": 2700 @@ -2035,6 +2039,10 @@ "category": "Error", "code": 2704 }, + "Interface declaration cannot contain a spread property.": { + "category": "Error", + "code": 2705 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index e214bbd67ca7d..7c865684a16b7 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -76,6 +76,8 @@ namespace ts { visitNode(cbNode, (node).objectAssignmentInitializer); case SyntaxKind.SpreadAssignment: return visitNode(cbNode, (node).expression); + case SyntaxKind.SpreadTypeAssignment: + return visitNode(cbNode, (node as SpreadTypeAssignment).type); case SyntaxKind.Parameter: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -2375,6 +2377,9 @@ namespace ts { if (token() === SyntaxKind.OpenBracketToken) { return true; } + if (token() === SyntaxKind.DotDotDotToken) { + return true; + } // Try to get the first property-like token following all modifiers if (isLiteralPropertyName()) { idToken = token(); @@ -2394,11 +2399,17 @@ namespace ts { } function parseTypeMember(): TypeElement { - if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { - return parseSignatureMember(SyntaxKind.CallSignature); - } - if (token() === SyntaxKind.NewKeyword && lookAhead(isStartOfConstructSignature)) { - return parseSignatureMember(SyntaxKind.ConstructSignature); + switch (token()) { + case SyntaxKind.OpenParenToken: + case SyntaxKind.LessThanToken: + return parseSignatureMember(SyntaxKind.CallSignature); + case SyntaxKind.NewKeyword: + if (lookAhead(isStartOfConstructSignature)) { + return parseSignatureMember(SyntaxKind.ConstructSignature); + } + break; + case SyntaxKind.DotDotDotToken: + return parseSpreadTypeAssignment(); } const fullStart = getNodePos(); const modifiers = parseModifiers(); @@ -2408,6 +2419,14 @@ namespace ts { return parsePropertyOrMethodSignature(fullStart, modifiers); } + function parseSpreadTypeAssignment() { + const element = createNode(SyntaxKind.SpreadTypeAssignment, scanner.getStartPos()) as SpreadTypeAssignment; + 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 008cbe3dfb48f..ee8771e6ebb68 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -323,6 +323,7 @@ namespace ts { PropertyAssignment, ShorthandPropertyAssignment, SpreadAssignment, + SpreadTypeAssignment, // Enum EnumMember, @@ -663,6 +664,11 @@ namespace ts { initializer?: Expression; // Optional initializer } + export interface SpreadTypeAssignment extends TypeElement { + kind: SyntaxKind.SpreadTypeAssignment; + type: TypeNode; + } + export interface PropertyDeclaration extends ClassElement { kind: SyntaxKind.PropertyDeclaration; questionToken?: QuestionToken; // Present for use with reporting a grammar error @@ -2594,7 +2600,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 or intersection type + SyntheticProperty = 0x10000000, // Property in union, intersection or spread type Optional = 0x20000000, // Optional property ExportStar = 0x40000000, // Export * declaration @@ -2785,6 +2791,7 @@ 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 type /* @internal */ Nullable = Undefined | Null, @@ -2802,13 +2809,13 @@ namespace ts { BooleanLike = Boolean | BooleanLiteral, EnumLike = Enum | EnumLiteral, UnionOrIntersection = Union | Intersection, - StructuredType = Object | Union | Intersection, + StructuredType = Object | Union | Intersection | Spread, StructuredOrTypeParameter = StructuredType | TypeParameter | Index, TypeVariable = TypeParameter | IndexedAccess, // '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, + Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol | Spread, NotUnionOrUnit = Any | ESSymbol | Object, /* @internal */ RequiresWidening = ContainsWideningType | ContainsObjectLiteral, @@ -2928,6 +2935,13 @@ namespace ts { export type StructuredType = ObjectType | UnionType | IntersectionType; + /* @internal */ + export interface SpreadType extends Type { + left: SpreadType | ResolvedType; + // Note: probably should just make this to be Type now + right: TypeParameter | IntersectionType | IndexType | IndexedAccessType | ResolvedType; + } + /* @internal */ // An instantiated anonymous type has a target and a mapper export interface AnonymousType extends ObjectType { @@ -2951,7 +2965,7 @@ namespace ts { } /* @internal */ - // Resolved object, union, or intersection type + // Resolved object, spread, union, or intersection type export interface ResolvedType extends ObjectType, UnionOrIntersectionType { members: SymbolTable; // Properties by name properties: Symbol[]; // Properties From dd08d554feb4ded4e1b716df33a37b13fb5e21ec Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 4 Jan 2017 14:32:28 -0800 Subject: [PATCH 2/9] Object.assign's now uses spreads --- src/lib/es2015.core.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/es2015.core.d.ts b/src/lib/es2015.core.d.ts index 356512ecf5848..73c71b3d6226c 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 e7f9a9c4691a8844f0810ea012b36ce85a168be8 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 4 Jan 2017 14:33:01 -0800 Subject: [PATCH 3/9] Test spread types and update baselines --- .../reference/interfaceSpread.errors.txt | 6 +- tests/baselines/reference/interfaceSpread.js | 2 +- tests/baselines/reference/objectSpread.js | 42 ++- .../baselines/reference/objectSpread.symbols | 248 ++++++++++++------ tests/baselines/reference/objectSpread.types | 128 ++++++++- .../reference/objectSpreadGeneric.errors.txt | 148 +++++++++++ .../reference/objectSpreadGeneric.js | 141 ++++++++++ .../objectSpreadIndexSignature.errors.txt | 38 +++ .../reference/objectSpreadIndexSignature.js | 42 ++- .../objectSpreadIndexSignature.symbols | 45 ---- .../objectSpreadIndexSignature.types | 52 ---- .../reference/objectSpreadInference.symbols | 6 + .../reference/objectSpreadInference.types | 12 +- .../reference/objectSpreadIntersection.js | 1 - .../objectSpreadIntersection.symbols | 10 +- .../reference/objectSpreadIntersection.types | 19 +- .../reference/objectSpreadNegative.errors.txt | 103 +++++--- .../reference/objectSpreadNegative.js | 68 ++--- .../reference/objectSpreadScenarios.symbols | 5 + .../reference/objectSpreadScenarios.types | 10 +- .../baselines/reference/objectSpreadUnion.js | 2 - .../reference/objectSpreadUnion.symbols | 6 +- .../reference/objectSpreadUnion.types | 10 +- .../spreadInvalidArgumentType.errors.txt | 45 +--- .../reference/spreadInvalidArgumentType.js | 35 +-- .../compiler/spreadInvalidArgumentType.ts | 18 +- .../types/spread/interfaceSpread.ts | 8 + .../conformance/types/spread/objectSpread.ts | 21 +- .../types/spread/objectSpreadGeneric.ts | 72 +++++ .../spread/objectSpreadIndexSignature.ts | 18 +- .../types/spread/objectSpreadInference.ts | 19 ++ .../types/spread/objectSpreadIntersection.ts | 35 +++ .../types/spread/objectSpreadNegative.ts | 37 ++- .../types/spread/objectSpreadScenarios.ts | 17 ++ .../types/spread/objectSpreadUnion.ts | 21 ++ .../fourslash/findAllRefsForObjectSpread.ts | 4 +- .../fourslash/goToDefinitionObjectSpread.ts | 4 +- tests/cases/fourslash/renameObjectSpread.ts | 4 +- 38 files changed, 1105 insertions(+), 397 deletions(-) create mode 100644 tests/baselines/reference/objectSpreadGeneric.errors.txt create mode 100644 tests/baselines/reference/objectSpreadGeneric.js create mode 100644 tests/baselines/reference/objectSpreadIndexSignature.errors.txt delete mode 100644 tests/baselines/reference/objectSpreadIndexSignature.symbols delete mode 100644 tests/baselines/reference/objectSpreadIndexSignature.types create mode 100644 tests/cases/conformance/types/spread/interfaceSpread.ts create mode 100644 tests/cases/conformance/types/spread/objectSpreadGeneric.ts create mode 100644 tests/cases/conformance/types/spread/objectSpreadInference.ts create mode 100644 tests/cases/conformance/types/spread/objectSpreadIntersection.ts create mode 100644 tests/cases/conformance/types/spread/objectSpreadScenarios.ts create mode 100644 tests/cases/conformance/types/spread/objectSpreadUnion.ts diff --git a/tests/baselines/reference/interfaceSpread.errors.txt b/tests/baselines/reference/interfaceSpread.errors.txt index c6acc63391278..9fc456c5567f0 100644 --- a/tests/baselines/reference/interfaceSpread.errors.txt +++ b/tests/baselines/reference/interfaceSpread.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/spread/interfaceSpread.ts(2,5): error TS2698: Interface declaration cannot contain a spread property. +tests/cases/conformance/types/spread/interfaceSpread.ts(2,5): error TS2705: Interface declaration cannot contain a spread property. tests/cases/conformance/types/spread/interfaceSpread.ts(7,10): error TS2339: Property 'jam' does not exist on type 'Congealed<{ jam: number; }, { peanutButter: number; }>'. tests/cases/conformance/types/spread/interfaceSpread.ts(8,10): error TS2339: Property 'peanutButter' does not exist on type 'Congealed<{ jam: number; }, { peanutButter: number; }>'. @@ -7,11 +7,11 @@ tests/cases/conformance/types/spread/interfaceSpread.ts(8,10): error TS2339: Pro interface Congealed { ...T ~~~~ -!!! error TS2698: Interface declaration cannot contain a spread property. +!!! error TS2705: Interface declaration cannot contain a spread property. ...U } - let sandwich: Congealed<{jam: number }, { peanutButter: number }>; + let sandwich: Congealed<{ jam: number }, { peanutButter: number }>; sandwich.jam; ~~~ !!! error TS2339: Property 'jam' does not exist on type 'Congealed<{ jam: number; }, { peanutButter: number; }>'. diff --git a/tests/baselines/reference/interfaceSpread.js b/tests/baselines/reference/interfaceSpread.js index 89f2531436667..cd01674884caa 100644 --- a/tests/baselines/reference/interfaceSpread.js +++ b/tests/baselines/reference/interfaceSpread.js @@ -4,7 +4,7 @@ interface Congealed { ...U } -let sandwich: Congealed<{jam: number }, { peanutButter: number }>; +let sandwich: Congealed<{ jam: number }, { peanutButter: number }>; sandwich.jam; sandwich.peanutButter; diff --git a/tests/baselines/reference/objectSpread.js b/tests/baselines/reference/objectSpread.js index 4305e17ab310f..b9bfb19d633ab 100644 --- a/tests/baselines/reference/objectSpread.js +++ b/tests/baselines/reference/objectSpread.js @@ -35,7 +35,9 @@ let getter: { a: number, c: number } = { ...op, c: 7 } getter.a = 12; -// functions result in { } +// null, undefined and functions result in { } +let spreadNull = { ...null }; +let spreadUndefined = { ...undefined }; let spreadFunc = { ...(function () { }) }; // any results in any @@ -79,6 +81,23 @@ 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] @@ -111,7 +130,9 @@ var propertyNested = { a: __assign({}, o) }; var op = { get a() { return 6; } }; var getter = __assign({}, op, { c: 7 }); getter.a = 12; -// functions result in { } +// null, undefined and functions result in { } +var spreadNull = __assign({}, null); +var spreadUndefined = __assign({}, undefined); var spreadFunc = __assign({}, (function () { })); // any results in any var anything; @@ -148,4 +169,21 @@ 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 35c10faa9c05d..7d5b8a527706c 100644 --- a/tests/baselines/reference/objectSpread.symbols +++ b/tests/baselines/reference/objectSpread.symbols @@ -165,70 +165,77 @@ getter.a = 12; >getter : Symbol(getter, Decl(objectSpread.ts, 32, 3)) >a : Symbol(a, Decl(objectSpread.ts, 32, 13)) -// functions result in { } +// null, undefined and functions result in { } +let spreadNull = { ...null }; +>spreadNull : Symbol(spreadNull, Decl(objectSpread.ts, 37, 3)) + +let spreadUndefined = { ...undefined }; +>spreadUndefined : Symbol(spreadUndefined, Decl(objectSpread.ts, 38, 3)) +>undefined : Symbol(undefined) + let spreadFunc = { ...(function () { }) }; ->spreadFunc : Symbol(spreadFunc, Decl(objectSpread.ts, 37, 3)) +>spreadFunc : Symbol(spreadFunc, Decl(objectSpread.ts, 39, 3)) // any results in any let anything: any; ->anything : Symbol(anything, Decl(objectSpread.ts, 40, 3)) +>anything : Symbol(anything, Decl(objectSpread.ts, 42, 3)) let spreadAny = { ...anything }; ->spreadAny : Symbol(spreadAny, Decl(objectSpread.ts, 41, 3)) ->anything : Symbol(anything, Decl(objectSpread.ts, 40, 3)) +>spreadAny : Symbol(spreadAny, Decl(objectSpread.ts, 43, 3)) +>anything : Symbol(anything, Decl(objectSpread.ts, 42, 3)) // methods are not enumerable class C { p = 1; m() { } } ->C : Symbol(C, Decl(objectSpread.ts, 41, 32)) ->p : Symbol(C.p, Decl(objectSpread.ts, 44, 9)) ->m : Symbol(C.m, Decl(objectSpread.ts, 44, 16)) +>C : Symbol(C, Decl(objectSpread.ts, 43, 32)) +>p : Symbol(C.p, Decl(objectSpread.ts, 46, 9)) +>m : Symbol(C.m, Decl(objectSpread.ts, 46, 16)) let c: C = new C() ->c : Symbol(c, Decl(objectSpread.ts, 45, 3)) ->C : Symbol(C, Decl(objectSpread.ts, 41, 32)) ->C : Symbol(C, Decl(objectSpread.ts, 41, 32)) +>c : Symbol(c, Decl(objectSpread.ts, 47, 3)) +>C : Symbol(C, Decl(objectSpread.ts, 43, 32)) +>C : Symbol(C, Decl(objectSpread.ts, 43, 32)) let spreadC: { p: number } = { ...c } ->spreadC : Symbol(spreadC, Decl(objectSpread.ts, 46, 3)) ->p : Symbol(p, Decl(objectSpread.ts, 46, 14)) ->c : Symbol(c, Decl(objectSpread.ts, 45, 3)) +>spreadC : Symbol(spreadC, Decl(objectSpread.ts, 48, 3)) +>p : Symbol(p, Decl(objectSpread.ts, 48, 14)) +>c : Symbol(c, Decl(objectSpread.ts, 47, 3)) // own methods are enumerable let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } }; ->cplus : Symbol(cplus, Decl(objectSpread.ts, 49, 3)) ->p : Symbol(p, Decl(objectSpread.ts, 49, 12)) ->plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) ->c : Symbol(c, Decl(objectSpread.ts, 45, 3)) ->plus : Symbol(plus, Decl(objectSpread.ts, 49, 48)) +>cplus : Symbol(cplus, Decl(objectSpread.ts, 51, 3)) +>p : Symbol(p, Decl(objectSpread.ts, 51, 12)) +>plus : Symbol(plus, Decl(objectSpread.ts, 51, 23)) +>c : Symbol(c, Decl(objectSpread.ts, 47, 3)) +>plus : Symbol(plus, Decl(objectSpread.ts, 51, 48)) cplus.plus(); ->cplus.plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) ->cplus : Symbol(cplus, Decl(objectSpread.ts, 49, 3)) ->plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) +>cplus.plus : Symbol(plus, Decl(objectSpread.ts, 51, 23)) +>cplus : Symbol(cplus, Decl(objectSpread.ts, 51, 3)) +>plus : Symbol(plus, Decl(objectSpread.ts, 51, 23)) // new field's type conflicting with existing field is OK let changeTypeAfter: { a: string, b: string } = ->changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 53, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 53, 22)) ->b : Symbol(b, Decl(objectSpread.ts, 53, 33)) +>changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 55, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 55, 22)) +>b : Symbol(b, Decl(objectSpread.ts, 55, 33)) { ...o, a: 'wrong type?' } >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 54, 11)) +>a : Symbol(a, Decl(objectSpread.ts, 56, 11)) let changeTypeBefore: { a: number, b: string } = ->changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 55, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 55, 23)) ->b : Symbol(b, Decl(objectSpread.ts, 55, 34)) +>changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 57, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 57, 23)) +>b : Symbol(b, Decl(objectSpread.ts, 57, 34)) { a: 'wrong type?', ...o }; ->a : Symbol(a, Decl(objectSpread.ts, 56, 5)) +>a : Symbol(a, Decl(objectSpread.ts, 58, 5)) >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) let changeTypeBoth: { a: string, b: number } = ->changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 57, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 57, 21)) ->b : Symbol(b, Decl(objectSpread.ts, 57, 32)) +>changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 59, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 59, 21)) +>b : Symbol(b, Decl(objectSpread.ts, 59, 32)) { ...o, ...swap }; >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) @@ -236,84 +243,169 @@ let changeTypeBoth: { a: string, b: number } = // optional let definiteBoolean: { sn: boolean }; ->definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 61, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 61, 22)) +>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 63, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 63, 22)) let definiteString: { sn: string }; ->definiteString : Symbol(definiteString, Decl(objectSpread.ts, 62, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 62, 21)) +>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 64, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 64, 21)) let optionalString: { sn?: string }; ->optionalString : Symbol(optionalString, Decl(objectSpread.ts, 63, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 63, 21)) +>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 65, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 65, 21)) let optionalNumber: { sn?: number }; ->optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 64, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 64, 21)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 66, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 66, 21)) let optionalUnionStops: { sn: string | number | boolean } = { ...definiteBoolean, ...definiteString, ...optionalNumber }; ->optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 65, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 65, 25)) ->definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 61, 3)) ->definiteString : Symbol(definiteString, Decl(objectSpread.ts, 62, 3)) ->optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 64, 3)) +>optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 67, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 67, 25)) +>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 63, 3)) +>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 64, 3)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 66, 3)) let optionalUnionDuplicates: { sn: string | number } = { ...definiteBoolean, ...definiteString, ...optionalString, ...optionalNumber }; ->optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 66, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 66, 30)) ->definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 61, 3)) ->definiteString : Symbol(definiteString, Decl(objectSpread.ts, 62, 3)) ->optionalString : Symbol(optionalString, Decl(objectSpread.ts, 63, 3)) ->optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 64, 3)) +>optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 68, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 68, 30)) +>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 63, 3)) +>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 64, 3)) +>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 65, 3)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 66, 3)) let allOptional: { sn?: string | number } = { ...optionalString, ...optionalNumber }; ->allOptional : Symbol(allOptional, Decl(objectSpread.ts, 67, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 67, 18)) ->optionalString : Symbol(optionalString, Decl(objectSpread.ts, 63, 3)) ->optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 64, 3)) +>allOptional : Symbol(allOptional, Decl(objectSpread.ts, 69, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 69, 18)) +>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 65, 3)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 66, 3)) // computed property let computedFirst: { a: number, b: string, "before everything": number } = ->computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 70, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 70, 20)) ->b : Symbol(b, Decl(objectSpread.ts, 70, 31)) +>computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 72, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 72, 20)) +>b : Symbol(b, Decl(objectSpread.ts, 72, 31)) { ['before everything']: 12, ...o, b: 'yes' } ->'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 71, 5)) +>'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 73, 5)) >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->b : Symbol(b, Decl(objectSpread.ts, 71, 38)) +>b : Symbol(b, Decl(objectSpread.ts, 73, 38)) let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = ->computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 72, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 72, 21)) ->b : Symbol(b, Decl(objectSpread.ts, 72, 32)) ->c : Symbol(c, Decl(objectSpread.ts, 72, 43)) +>computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 74, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 74, 21)) +>b : Symbol(b, Decl(objectSpread.ts, 74, 32)) +>c : Symbol(c, Decl(objectSpread.ts, 74, 43)) { ...o, ['in the middle']: 13, b: 'maybe?', ...o2 } >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 73, 11)) ->b : Symbol(b, Decl(objectSpread.ts, 73, 34)) +>'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 75, 11)) +>b : Symbol(b, Decl(objectSpread.ts, 75, 34)) >o2 : Symbol(o2, Decl(objectSpread.ts, 1, 3)) let computedAfter: { a: number, b: string, "at the end": number } = ->computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 74, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 74, 20)) ->b : Symbol(b, Decl(objectSpread.ts, 74, 31)) +>computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 76, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 76, 20)) +>b : Symbol(b, Decl(objectSpread.ts, 76, 31)) { ...o, b: 'yeah', ['at the end']: 14 } >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->b : Symbol(b, Decl(objectSpread.ts, 75, 11)) ->'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 75, 22)) +>b : Symbol(b, Decl(objectSpread.ts, 77, 11)) +>'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 77, 22)) // shortcut syntax let a = 12; ->a : Symbol(a, Decl(objectSpread.ts, 77, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 79, 3)) let shortCutted: { a: number, b: string } = { ...o, a } ->shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 78, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 78, 18)) ->b : Symbol(b, Decl(objectSpread.ts, 78, 29)) +>shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 80, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 80, 18)) +>b : Symbol(b, Decl(objectSpread.ts, 80, 29)) >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 78, 51)) - +>a : Symbol(a, Decl(objectSpread.ts, 80, 51)) + +// generics +function f(t: T, u: U): { ...T, ...U, id: string } { +>f : Symbol(f, Decl(objectSpread.ts, 80, 55)) +>T : Symbol(T, Decl(objectSpread.ts, 83, 11)) +>U : Symbol(U, Decl(objectSpread.ts, 83, 13)) +>t : Symbol(t, Decl(objectSpread.ts, 83, 17)) +>T : Symbol(T, Decl(objectSpread.ts, 83, 11)) +>u : Symbol(u, Decl(objectSpread.ts, 83, 22)) +>U : Symbol(U, Decl(objectSpread.ts, 83, 13)) +>T : Symbol(T, Decl(objectSpread.ts, 83, 11)) +>U : Symbol(U, Decl(objectSpread.ts, 83, 13)) +>id : Symbol(id, Decl(objectSpread.ts, 83, 43)) + + return { ...t, ...u, id: 'id' }; +>t : Symbol(t, Decl(objectSpread.ts, 83, 17)) +>u : Symbol(u, Decl(objectSpread.ts, 83, 22)) +>id : Symbol(id, Decl(objectSpread.ts, 84, 24)) +} + +let exclusive: { id: string, a: number, b: string, c: string, d: boolean } = +>exclusive : Symbol(exclusive, Decl(objectSpread.ts, 87, 3)) +>id : Symbol(id, Decl(objectSpread.ts, 87, 16)) +>a : Symbol(a, Decl(objectSpread.ts, 87, 28)) +>b : Symbol(b, Decl(objectSpread.ts, 87, 39)) +>c : Symbol(c, Decl(objectSpread.ts, 87, 50)) +>d : Symbol(d, Decl(objectSpread.ts, 87, 61)) + + f({ a: 1, b: 'yes' }, { c: 'no', d: false }) +>f : Symbol(f, Decl(objectSpread.ts, 80, 55)) +>a : Symbol(a, Decl(objectSpread.ts, 88, 7)) +>b : Symbol(b, Decl(objectSpread.ts, 88, 13)) +>c : Symbol(c, Decl(objectSpread.ts, 88, 27)) +>d : Symbol(d, Decl(objectSpread.ts, 88, 36)) + +let overlap: { id: string, a: number, b: string } = +>overlap : Symbol(overlap, Decl(objectSpread.ts, 89, 3)) +>id : Symbol(id, Decl(objectSpread.ts, 89, 14)) +>a : Symbol(a, Decl(objectSpread.ts, 89, 26)) +>b : Symbol(b, Decl(objectSpread.ts, 89, 37)) + + f({ a: 1 }, { a: 2, b: 'extra' }) +>f : Symbol(f, Decl(objectSpread.ts, 80, 55)) +>a : Symbol(a, Decl(objectSpread.ts, 90, 7)) +>a : Symbol(a, Decl(objectSpread.ts, 90, 17)) +>b : Symbol(b, Decl(objectSpread.ts, 90, 23)) + +let overlapConflict: { id:string, a: string } = +>overlapConflict : Symbol(overlapConflict, Decl(objectSpread.ts, 91, 3)) +>id : Symbol(id, Decl(objectSpread.ts, 91, 22)) +>a : Symbol(a, Decl(objectSpread.ts, 91, 33)) + + f({ a: 1 }, { a: 'mismatch' }) +>f : Symbol(f, Decl(objectSpread.ts, 80, 55)) +>a : Symbol(a, Decl(objectSpread.ts, 92, 7)) +>a : Symbol(a, Decl(objectSpread.ts, 92, 17)) + +let overwriteId: { id: string, a: number, c: number, d: string } = +>overwriteId : Symbol(overwriteId, Decl(objectSpread.ts, 93, 3)) +>id : Symbol(id, Decl(objectSpread.ts, 93, 18)) +>a : Symbol(a, Decl(objectSpread.ts, 93, 30)) +>c : Symbol(c, Decl(objectSpread.ts, 93, 41)) +>d : Symbol(d, Decl(objectSpread.ts, 93, 52)) + + f({ a: 1, id: true }, { c: 1, d: 'no' }) +>f : Symbol(f, Decl(objectSpread.ts, 80, 55)) +>a : Symbol(a, Decl(objectSpread.ts, 94, 7)) +>id : Symbol(id, Decl(objectSpread.ts, 94, 13)) +>c : Symbol(c, Decl(objectSpread.ts, 94, 27)) +>d : Symbol(d, Decl(objectSpread.ts, 94, 33)) + +class D { m() { }; q = 2; } +>D : Symbol(D, Decl(objectSpread.ts, 94, 44)) +>m : Symbol(D.m, Decl(objectSpread.ts, 96, 9)) +>q : Symbol(D.q, Decl(objectSpread.ts, 96, 18)) + +let classesAreWrong: { id: string, ...C, ...D } = +>classesAreWrong : Symbol(classesAreWrong, Decl(objectSpread.ts, 97, 3)) +>id : Symbol(id, Decl(objectSpread.ts, 97, 22)) +>C : Symbol(C, Decl(objectSpread.ts, 43, 32)) +>D : Symbol(D, Decl(objectSpread.ts, 94, 44)) + + f(new C(), new D()) +>f : Symbol(f, Decl(objectSpread.ts, 80, 55)) +>C : Symbol(C, Decl(objectSpread.ts, 43, 32)) +>D : Symbol(D, Decl(objectSpread.ts, 94, 44)) diff --git a/tests/baselines/reference/objectSpread.types b/tests/baselines/reference/objectSpread.types index a571bd0bb6330..2e4c82bb8a6b2 100644 --- a/tests/baselines/reference/objectSpread.types +++ b/tests/baselines/reference/objectSpread.types @@ -223,7 +223,17 @@ getter.a = 12; >a : number >12 : 12 -// functions result in { } +// null, undefined and functions result in { } +let spreadNull = { ...null }; +>spreadNull : {} +>{ ...null } : {} +>null : null + +let spreadUndefined = { ...undefined }; +>spreadUndefined : {} +>{ ...undefined } : {} +>undefined : undefined + let spreadFunc = { ...(function () { }) }; >spreadFunc : {} >{ ...(function () { }) } : {} @@ -407,4 +417,120 @@ let shortCutted: { a: number, b: string } = { ...o, a } >o : { a: number; b: string; } >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 : T +>u : U +>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 new file mode 100644 index 0000000000000..d722ca316c245 --- /dev/null +++ b/tests/baselines/reference/objectSpreadGeneric.errors.txt @@ -0,0 +1,148 @@ +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 TS90010: Type '{ first: string; ...T; ...U }' is not assignable to type '{ first: string; ...T; ...U }'. Two different types with this name exist, but they are unrelated. +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 TS90010: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(34,15): 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,15): error TS90010: 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; }'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(38,15): 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,15): 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,15): 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 TS90010: Type '{ first: string; ...T; ...U }' is not assignable to type '{ first: string; ...T; ...U }'. Two different types with this name exist, but they are unrelated. + + 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 TS90010: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. Two different types with this name exist, but they are unrelated. + { 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 TS90010: 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; }'. Two different types with this name exist, but they are unrelated. + { 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 new file mode 100644 index 0000000000000..9f9c45d9467a9 --- /dev/null +++ b/tests/baselines/reference/objectSpreadGeneric.js @@ -0,0 +1,141 @@ +//// [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 new file mode 100644 index 0000000000000..0e1d0dc724224 --- /dev/null +++ b/tests/baselines/reference/objectSpreadIndexSignature.errors.txt @@ -0,0 +1,38 @@ +tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts(6,39): error TS2699: Type literals with spreads cannot contain index, call or constructor signatures. +tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts(27,20): error TS2699: Type literals with spreads cannot contain index, call or constructor 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 constructor signatures. + let n: number = c.a; + let s: string = c[12]; + interface Indexed { + [n: string]: number; + a: number; + } + interface Indexed2 { + [n: string]: boolean; + c: boolean; + } + let indexed: Indexed; + let indexed2: Indexed2; + let i: { ...Indexed, b: number }; + // only indexed has indexer, so i[101]: any + i[101]; + let ii: { ...Indexed, ...Indexed2, b: boolean, d: number }; + // both have indexer, so i[1001]: number | boolean + 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 constructor signatures. + } + \ No newline at end of file diff --git a/tests/baselines/reference/objectSpreadIndexSignature.js b/tests/baselines/reference/objectSpreadIndexSignature.js index 22e92e6a844bf..f45ab643d4f9e 100644 --- a/tests/baselines/reference/objectSpreadIndexSignature.js +++ b/tests/baselines/reference/objectSpreadIndexSignature.js @@ -1,4 +1,12 @@ //// [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; @@ -9,28 +17,36 @@ interface Indexed2 { } let indexed: Indexed; let indexed2: Indexed2; -let i = { ...indexed, b: 11 }; +let i: { ...Indexed, b: number }; // only indexed has indexer, so i[101]: any i[101]; -let ii = { ...indexed, ...indexed2 }; +let ii: { ...Indexed, ...Indexed2, b: boolean, d: number }; // both have indexer, so i[1001]: number | boolean -ii[1001]; +let nb: number | boolean = ii[1001]; + +function f(t: T) { + let i: { ...T, [n: number]: string }; +} //// [objectSpreadIndexSignature.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]; +var C = (function () { + function C() { } - return t; -}; + return C; +}()); +// index signatures are not allowed in object literals with spread types +var c; +var n = c.a; +var s = c[12]; var indexed; var indexed2; -var i = __assign({}, indexed, { b: 11 }); +var i; // only indexed has indexer, so i[101]: any i[101]; -var ii = __assign({}, indexed, indexed2); +var ii; // both have indexer, so i[1001]: number | boolean -ii[1001]; +var nb = ii[1001]; +function f(t) { + var i; +} diff --git a/tests/baselines/reference/objectSpreadIndexSignature.symbols b/tests/baselines/reference/objectSpreadIndexSignature.symbols deleted file mode 100644 index cd64b15719699..0000000000000 --- a/tests/baselines/reference/objectSpreadIndexSignature.symbols +++ /dev/null @@ -1,45 +0,0 @@ -=== 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)) ->indexed : Symbol(indexed, Decl(objectSpreadIndexSignature.ts, 8, 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)) ->indexed : Symbol(indexed, Decl(objectSpreadIndexSignature.ts, 8, 3)) ->indexed2 : Symbol(indexed2, Decl(objectSpreadIndexSignature.ts, 9, 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 deleted file mode 100644 index 5eebc2ffa02b7..0000000000000 --- a/tests/baselines/reference/objectSpreadIndexSignature.types +++ /dev/null @@ -1,52 +0,0 @@ -=== 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 : Indexed ->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 : Indexed ->indexed2 : Indexed2 - -// 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/objectSpreadInference.symbols b/tests/baselines/reference/objectSpreadInference.symbols index ddecc4d7e5d3f..cc1b162474684 100644 --- a/tests/baselines/reference/objectSpreadInference.symbols +++ b/tests/baselines/reference/objectSpreadInference.symbols @@ -66,6 +66,8 @@ 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" }); >infer : Symbol(infer, Decl(objectSpreadInference.ts, 4, 1)) +>w : Symbol(w, Decl(objectSpreadInference.ts, 7, 26)) +>x : Symbol(x, Decl(objectSpreadInference.ts, 7, 31)) >a : Symbol(a, Decl(objectSpreadInference.ts, 9, 30)) >y : Symbol(y, Decl(objectSpreadInference.ts, 7, 37)) >b : Symbol(b, Decl(objectSpreadInference.ts, 9, 36)) @@ -82,12 +84,16 @@ let c: { c: number }; let i1 = infer({ ...b, ...c, a: 12 }); >i1 : Symbol(i1, Decl(objectSpreadInference.ts, 14, 3)) >infer : Symbol(infer, Decl(objectSpreadInference.ts, 4, 1)) +>b : Symbol(b, Decl(objectSpreadInference.ts, 11, 3)) +>c : Symbol(c, Decl(objectSpreadInference.ts, 12, 3)) >a : Symbol(a, Decl(objectSpreadInference.ts, 14, 28)) // can only infer { t: {}, u: {}, v: {} } let i2 = infer2({ ...b, ...c, a: 12 }); >i2 : Symbol(i2, Decl(objectSpreadInference.ts, 16, 3)) >infer2 : Symbol(infer2, Decl(objectSpreadInference.ts, 5, 79)) +>b : Symbol(b, Decl(objectSpreadInference.ts, 11, 3)) +>c : Symbol(c, Decl(objectSpreadInference.ts, 12, 3)) >a : Symbol(a, Decl(objectSpreadInference.ts, 16, 29)) // can only infer { t: {}, u: {}, v: {} } diff --git a/tests/baselines/reference/objectSpreadInference.types b/tests/baselines/reference/objectSpreadInference.types index 3e71e29b83c48..0450ad06fc0d7 100644 --- a/tests/baselines/reference/objectSpreadInference.types +++ b/tests/baselines/reference/objectSpreadInference.types @@ -68,8 +68,8 @@ function generic(w: W, x: X, y: Y) { >infer({ ...w, ...x, a: y, b: "different type" }) : { t: {}; u: {}; v: {}; } >infer : (tuv: { ...T; ...U; a: V; }) => { t: T; u: U; v: V; } >{ ...w, ...x, a: y, b: "different type" } : { ...W; ...X; a: Y; b: string; } ->w : any ->x : any +>w : W +>x : X >a : Y >y : Y >b : string @@ -89,8 +89,8 @@ let i1 = infer({ ...b, ...c, a: 12 }); >infer({ ...b, ...c, a: 12 }) : { t: {}; u: {}; v: {}; } >infer : (tuv: { ...T; ...U; a: V; }) => { t: T; u: U; v: V; } >{ ...b, ...c, a: 12 } : { a: number; c: number; b: number; } ->b : any ->c : any +>b : { b: number; } +>c : { c: number; } >a : number >12 : 12 @@ -100,8 +100,8 @@ let i2 = infer2({ ...b, ...c, a: 12 }); >infer2({ ...b, ...c, a: 12 }) : { t: {}; u: {}; v: {}; } >infer2 : (utv: { ...U; a: V; ...T }) => { t: T; u: U; v: V; } >{ ...b, ...c, a: 12 } : { a: number; c: number; b: number; } ->b : any ->c : any +>b : { b: number; } +>c : { c: number; } >a : number >12 : 12 diff --git a/tests/baselines/reference/objectSpreadIntersection.js b/tests/baselines/reference/objectSpreadIntersection.js index 2ec6ad35413a3..8f337836ac55c 100644 --- a/tests/baselines/reference/objectSpreadIntersection.js +++ b/tests/baselines/reference/objectSpreadIntersection.js @@ -34,7 +34,6 @@ function iteratedIntersectionUnion(t: T, u: U, v: V): void { let result = { ...tu, ...uv, id: 'qux' }; let assignable: { ...(T & U), ...(U | V), id: string } = result; } - //// [objectSpreadIntersection.js] diff --git a/tests/baselines/reference/objectSpreadIntersection.symbols b/tests/baselines/reference/objectSpreadIntersection.symbols index bc63cb11348e4..b2ef5add21328 100644 --- a/tests/baselines/reference/objectSpreadIntersection.symbols +++ b/tests/baselines/reference/objectSpreadIntersection.symbols @@ -23,6 +23,8 @@ function iteratedUnionIntersection(t: T, u: U, v: V): void { let result = { ...tu, ...uv, id: 'foo' }; >result : Symbol(result, Decl(objectSpreadIntersection.ts, 3, 7)) +>tu : Symbol(tu, Decl(objectSpreadIntersection.ts, 1, 7)) +>uv : Symbol(uv, Decl(objectSpreadIntersection.ts, 2, 7)) >id : Symbol(id, Decl(objectSpreadIntersection.ts, 3, 32)) let assignable: { ...(T | U), ...(U & V), id: string } = result; @@ -63,6 +65,8 @@ let b12: B1 & B2; let result = { ...a12, ...b12 }; >result : Symbol(result, Decl(objectSpreadIntersection.ts, 13, 3)) +>a12 : Symbol(a12, Decl(objectSpreadIntersection.ts, 11, 3)) +>b12 : Symbol(b12, Decl(objectSpreadIntersection.ts, 12, 3)) let sn: number & string = result.a; >sn : Symbol(sn, Decl(objectSpreadIntersection.ts, 14, 3)) @@ -104,6 +108,7 @@ function tripleIntersection(t: T, u: U, v: V): void { let result = { ...tuv, id: 'bar' }; >result : Symbol(result, Decl(objectSpreadIntersection.ts, 20, 7)) +>tuv : Symbol(tuv, Decl(objectSpreadIntersection.ts, 19, 7)) >id : Symbol(id, Decl(objectSpreadIntersection.ts, 20, 26)) let assignable: { ...(T & U & V), id: string } = result; @@ -138,6 +143,8 @@ function iteratedDoubleIntersection(t: T, u: U, v: V): void { let result = { ...tu, ...uv, id: 'baz' }; >result : Symbol(result, Decl(objectSpreadIntersection.ts, 26, 7)) +>tu : Symbol(tu, Decl(objectSpreadIntersection.ts, 24, 7)) +>uv : Symbol(uv, Decl(objectSpreadIntersection.ts, 25, 7)) >id : Symbol(id, Decl(objectSpreadIntersection.ts, 26, 32)) let assignable: { ...(T & U), ...(U & V), id: string } = result; @@ -173,6 +180,8 @@ function iteratedIntersectionUnion(t: T, u: U, v: V): void { let result = { ...tu, ...uv, id: 'qux' }; >result : Symbol(result, Decl(objectSpreadIntersection.ts, 32, 7)) +>tu : Symbol(tu, Decl(objectSpreadIntersection.ts, 30, 7)) +>uv : Symbol(uv, Decl(objectSpreadIntersection.ts, 31, 7)) >id : Symbol(id, Decl(objectSpreadIntersection.ts, 32, 32)) let assignable: { ...(T & U), ...(U | V), id: string } = result; @@ -185,4 +194,3 @@ function iteratedIntersectionUnion(t: T, u: U, v: V): void { >result : Symbol(result, Decl(objectSpreadIntersection.ts, 32, 7)) } - diff --git a/tests/baselines/reference/objectSpreadIntersection.types b/tests/baselines/reference/objectSpreadIntersection.types index e6a7b7c19ee7f..fe1259e37a762 100644 --- a/tests/baselines/reference/objectSpreadIntersection.types +++ b/tests/baselines/reference/objectSpreadIntersection.types @@ -24,8 +24,8 @@ function iteratedUnionIntersection(t: T, u: U, v: V): void { let result = { ...tu, ...uv, id: 'foo' }; >result : { ...T; ...U & V; id: string; } | { ...U; ...U & V; id: string; } >{ ...tu, ...uv, id: 'foo' } : { ...T; ...U & V; id: string; } | { ...U; ...U & V; id: string; } ->tu : any ->uv : any +>tu : T | U +>uv : U & V >id : string >'foo' : "foo" @@ -68,8 +68,8 @@ let b12: B1 & B2; let result = { ...a12, ...b12 }; >result : { b: number & string; a: number & string; } >{ ...a12, ...b12 } : { b: number & string; a: number & string; } ->a12 : any ->b12 : any +>a12 : A1 & A2 +>b12 : B1 & B2 let sn: number & string = result.a; >sn : number & string @@ -113,7 +113,7 @@ function tripleIntersection(t: T, u: U, v: V): void { let result = { ...tuv, id: 'bar' }; >result : { ...T & U & V; id: string; } >{ ...tuv, id: 'bar' } : { ...T & U & V; id: string; } ->tuv : any +>tuv : T & U & V >id : string >'bar' : "bar" @@ -150,8 +150,8 @@ function iteratedDoubleIntersection(t: T, u: U, v: V): void { let result = { ...tu, ...uv, id: 'baz' }; >result : { ...T & U; ...U & V; id: string; } >{ ...tu, ...uv, id: 'baz' } : { ...T & U; ...U & V; id: string; } ->tu : any ->uv : any +>tu : T & U +>uv : U & V >id : string >'baz' : "baz" @@ -189,8 +189,8 @@ function iteratedIntersectionUnion(t: T, u: U, v: V): void { let result = { ...tu, ...uv, id: 'qux' }; >result : { ...T & U; ...U; id: string; } | { ...T & U; ...V; id: string; } >{ ...tu, ...uv, id: 'qux' } : { ...T & U; ...U; id: string; } | { ...T & U; ...V; id: string; } ->tu : any ->uv : any +>tu : T & U +>uv : U | V >id : string >'qux' : "qux" @@ -204,4 +204,3 @@ function iteratedIntersectionUnion(t: T, u: U, v: V): void { >result : { ...T & U; ...U; id: string; } | { ...T & U; ...V; id: string; } } - diff --git a/tests/baselines/reference/objectSpreadNegative.errors.txt b/tests/baselines/reference/objectSpreadNegative.errors.txt index 17f07bc06a296..5d6fd1b4e9d62 100644 --- a/tests/baselines/reference/objectSpreadNegative.errors.txt +++ b/tests/baselines/reference/objectSpreadNegative.errors.txt @@ -1,24 +1,30 @@ -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; }'. +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; }'. Property 'sn' is optional in type '{ sn?: string | number; }' but required in type '{ sn: string | number; }'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(23,1): error TS2322: Type '{ s: string; }' is not assignable to type '{ s: string; b: boolean; }'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(20,5): 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(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,19): error TS2698: Spread types may only be created from object types. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(33,19): error TS2698: Spread types may only be created from object types. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(35,20): error TS2698: Spread types may only be created from object types. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(37,19): error TS2698: Spread types may only be created from object types. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(42,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(46,12): error TS2339: Property 'b' does not exist on type '{}'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(52,9): error TS2339: Property 'm' does not exist on type '{ p: number; }'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(56,14): error TS2698: Spread types may only be created from object types. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(59,14): error TS2698: Spread types may only be created from object types. +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(35,19): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(36,19): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(38,20): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(40,19): error TS2698: Spread types may only be created from object types. +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 constructor signatures. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(57,69): error TS2699: Type literals with spreads cannot contain index, call or constructor 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 (15 errors) ==== +==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (21 errors) ==== let o = { a: 1, b: 'no' } /// private propagates @@ -28,9 +34,7 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(59,14): error TS269 class PublicX { public x: number; } - let publicX: PublicX; - let privateOptionalX: PrivateOptionalX; - let o2 = { ...publicX, ...privateOptionalX }; + let o2: { ...PublicX, ...PrivateOptionalX }; let sn: number = o2.x; // error, x is private ~ !!! error TS2339: Property 'x' does not exist on type '{}'. @@ -45,16 +49,15 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(59,14): error TS269 // assignability as target interface Bool { b: boolean }; interface Str { s: string }; - let spread = { ...{ b: true }, ...{s: "foo" } }; - spread = { s: "foo" }; // error, missing 'b' - ~~~~~~ + let spread: { ...Bool, ...Str } = { 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 = { b: false }; + let b: Bool; spread = b; // error, missing 's' ~~~~~~ -!!! error TS2322: Type '{ b: boolean; }' is not assignable to type '{ s: string; b: boolean; }'. -!!! error TS2322: Property 's' is missing in type '{ b: boolean; }'. +!!! error TS2322: Type 'Bool' is not assignable to type '{ s: string; b: boolean; }'. +!!! error TS2322: Property 's' is missing in type 'Bool'. // literal repeats are not allowed, but spread repeats are fine let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' } @@ -64,6 +67,16 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(59,14): error TS269 !!! 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 are not allowed let spreadNum = { ...12 }; ~~~~~ @@ -101,23 +114,27 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(59,14): error TS269 ~ !!! error TS2339: Property 'm' does not exist on type '{ p: number; }'. - // 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 { + let callableConstructableSpread: { ...PublicX, (n: number): number, new (p: number) }; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2699: Type literals with spreads cannot contain index, call or constructor signatures. + ~~~~~~~~~~~~~~~ +!!! error TS2699: Type literals with spreads cannot contain index, call or constructor 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 TS2698: Spread types may only be created from object types. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ ...U }' is not assignable to type 'U'. } - 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 dff84355370e7..e6283271172ca 100644 --- a/tests/baselines/reference/objectSpreadNegative.js +++ b/tests/baselines/reference/objectSpreadNegative.js @@ -8,9 +8,7 @@ class PrivateOptionalX { class PublicX { public x: number; } -let publicX: PublicX; -let privateOptionalX: PrivateOptionalX; -let o2 = { ...publicX, ...privateOptionalX }; +let o2: { ...PublicX, ...PrivateOptionalX }; let sn: number = o2.x; // error, x is private let optionalString: { sn?: string }; let optionalNumber: { sn?: number }; @@ -20,15 +18,20 @@ let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumbe // assignability as target interface Bool { b: boolean }; interface Str { s: string }; -let spread = { ...{ b: true }, ...{s: "foo" } }; -spread = { s: "foo" }; // error, missing 'b' -let b = { b: false }; +let spread: { ...Bool, ...Str } = { s: "foo" }; // error, missing 'b' +let b: Bool; 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 are not allowed let spreadNum = { ...12 }; let spreadSum = { ...1 + 1 }; @@ -52,21 +55,17 @@ let c: C = new C() let spreadC = { ...c } spreadC.m(); // error 'm' is not in '{ ... c }' -// generics -function f(t: T, u: U) { - return { ...t, ...u, id: 'id' }; -} -function override(initial: U, override: U): U { +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 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] @@ -90,22 +89,24 @@ var PublicX = (function () { } return PublicX; }()); -var publicX; -var privateOptionalX; -var o2 = __assign({}, publicX, privateOptionalX); +var o2; var sn = o2.x; // error, x is private var optionalString; var optionalNumber; var allOptional = __assign({}, optionalString, optionalNumber); ; ; -var spread = __assign({ b: true }, { s: "foo" }); -spread = { s: "foo" }; // error, missing 'b' -var b = { b: false }; +var spread = { s: "foo" }; // error, missing 'b' +var b; 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 +var spreadNull = __assign({}, null); +spreadNull.null; +var spreadUndefined = __assign({}, undefined); +spreadUndefined.undefined; // primitives are not allowed var spreadNum = __assign({}, 12); var spreadSum = __assign({}, 1 + 1); @@ -132,14 +133,13 @@ var C = (function () { var c = new C(); var spreadC = __assign({}, c); spreadC.m(); // error 'm' is not in '{ ... c }' -// generics -function f(t, u) { - return __assign({}, t, u, { id: 'id' }); -} -function override(initial, override) { +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 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/objectSpreadScenarios.symbols b/tests/baselines/reference/objectSpreadScenarios.symbols index cf1e1833ac968..df27f89922ac6 100644 --- a/tests/baselines/reference/objectSpreadScenarios.symbols +++ b/tests/baselines/reference/objectSpreadScenarios.symbols @@ -18,6 +18,8 @@ function override(initial: U, override: U): { ...U, ...U } { >U : Symbol(U, Decl(objectSpreadScenarios.ts, 2, 18)) return { ...initial, ...override }; +>initial : Symbol(initial, Decl(objectSpreadScenarios.ts, 2, 21)) +>override : Symbol(override, Decl(objectSpreadScenarios.ts, 2, 32)) } function update(this: { u: { ...U } }, override: U): void { >update : Symbol(update, Decl(objectSpreadScenarios.ts, 4, 1)) @@ -35,6 +37,7 @@ function update(this: { u: { ...U } }, override: U): void { >this.u : Symbol(u, Decl(objectSpreadScenarios.ts, 5, 26)) >this : Symbol(this, Decl(objectSpreadScenarios.ts, 5, 19)) >u : Symbol(u, Decl(objectSpreadScenarios.ts, 5, 26)) +>override : Symbol(override, Decl(objectSpreadScenarios.ts, 5, 41)) } function mixin(one: T, two: U): { ...T, ...U } { >mixin : Symbol(mixin, Decl(objectSpreadScenarios.ts, 7, 1)) @@ -48,6 +51,8 @@ function mixin(one: T, two: U): { ...T, ...U } { >U : Symbol(U, Decl(objectSpreadScenarios.ts, 8, 17)) return { ...one, ...two }; +>one : Symbol(one, Decl(objectSpreadScenarios.ts, 8, 21)) +>two : Symbol(two, Decl(objectSpreadScenarios.ts, 8, 28)) } let a1: A1 = { a: true }; >a1 : Symbol(a1, Decl(objectSpreadScenarios.ts, 11, 3)) diff --git a/tests/baselines/reference/objectSpreadScenarios.types b/tests/baselines/reference/objectSpreadScenarios.types index 2d1aa47bd50a8..483a92cdb354e 100644 --- a/tests/baselines/reference/objectSpreadScenarios.types +++ b/tests/baselines/reference/objectSpreadScenarios.types @@ -19,8 +19,8 @@ function override(initial: U, override: U): { ...U, ...U } { return { ...initial, ...override }; >{ ...initial, ...override } : { ...U } ->initial : any ->override : any +>initial : U +>override : U } function update(this: { u: { ...U } }, override: U): void { >update : (this: { u: { ...U }; }, override: U) => void @@ -40,7 +40,7 @@ function update(this: { u: { ...U } }, override: U): void { >this.u : { ...U } >this : { u: { ...U }; } >u : { ...U } ->override : any +>override : U } function mixin(one: T, two: U): { ...T, ...U } { >mixin : (one: T, two: U) => { ...T; ...U } @@ -55,8 +55,8 @@ function mixin(one: T, two: U): { ...T, ...U } { return { ...one, ...two }; >{ ...one, ...two } : { ...T; ...U } ->one : any ->two : any +>one : T +>two : U } let a1: A1 = { a: true }; >a1 : A1 diff --git a/tests/baselines/reference/objectSpreadUnion.js b/tests/baselines/reference/objectSpreadUnion.js index b3a114c772218..10342e82f9b34 100644 --- a/tests/baselines/reference/objectSpreadUnion.js +++ b/tests/baselines/reference/objectSpreadUnion.js @@ -20,8 +20,6 @@ function iteratedDoubleUnion(t: T, u: U, v: V): void { 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; } - - //// [objectSpreadUnion.js] diff --git a/tests/baselines/reference/objectSpreadUnion.symbols b/tests/baselines/reference/objectSpreadUnion.symbols index d630fde518b52..26c11cd580f27 100644 --- a/tests/baselines/reference/objectSpreadUnion.symbols +++ b/tests/baselines/reference/objectSpreadUnion.symbols @@ -15,6 +15,7 @@ let a12: A1 | A2; let result = { ...a12 }; >result : Symbol(result, Decl(objectSpreadUnion.ts, 4, 3)) +>a12 : Symbol(a12, Decl(objectSpreadUnion.ts, 3, 3)) let sn: number | string = result.a; >sn : Symbol(sn, Decl(objectSpreadUnion.ts, 5, 3)) @@ -48,6 +49,7 @@ function tripleUnion(t: T, u: U, v: V): void { let result = { ...tuv, id: 'foo' }; >result : Symbol(result, Decl(objectSpreadUnion.ts, 10, 7)) +>tuv : Symbol(tuv, Decl(objectSpreadUnion.ts, 9, 7)) >id : Symbol(id, Decl(objectSpreadUnion.ts, 10, 26)) let expected: { ...T, id: string } | { ...U, id: string } | { ...V, id: string } = result; @@ -92,6 +94,8 @@ function iteratedDoubleUnion(t: T, u: U, v: V): void { let result = { ...tu, ...uv, id: 'bar' }; >result : Symbol(result, Decl(objectSpreadUnion.ts, 17, 7)) +>tu : Symbol(tu, Decl(objectSpreadUnion.ts, 15, 7)) +>uv : Symbol(uv, Decl(objectSpreadUnion.ts, 16, 7)) >id : Symbol(id, Decl(objectSpreadUnion.ts, 17, 32)) let expected: { ...T, ...U, id: string } | { ...T, ...V, id: string } | { ...U, id: string } | { ...U, ...V, id: string }; @@ -118,5 +122,3 @@ function iteratedDoubleUnion(t: T, u: U, v: V): void { >result : Symbol(result, Decl(objectSpreadUnion.ts, 17, 7)) } - - diff --git a/tests/baselines/reference/objectSpreadUnion.types b/tests/baselines/reference/objectSpreadUnion.types index 20633295acba3..7733aadb0cb49 100644 --- a/tests/baselines/reference/objectSpreadUnion.types +++ b/tests/baselines/reference/objectSpreadUnion.types @@ -16,7 +16,7 @@ let a12: A1 | A2; let result = { ...a12 }; >result : { a: number; } | { a: string; } >{ ...a12 } : { a: number; } | { a: string; } ->a12 : any +>a12 : A1 | A2 let sn: number | string = result.a; >sn : string | number @@ -51,7 +51,7 @@ function tripleUnion(t: T, u: U, v: V): void { let result = { ...tuv, id: 'foo' }; >result : { ...T; id: string; } | { ...U; id: string; } | { ...V; id: string; } >{ ...tuv, id: 'foo' } : { ...T; id: string; } | { ...U; id: string; } | { ...V; id: string; } ->tuv : any +>tuv : T | U | V >id : string >'foo' : "foo" @@ -98,8 +98,8 @@ function iteratedDoubleUnion(t: T, u: U, v: V): void { let result = { ...tu, ...uv, id: 'bar' }; >result : { ...U; id: string; } | { ...T; ...U; id: string; } | { ...T; ...V; id: string; } | { ...U; ...V; id: string; } >{ ...tu, ...uv, id: 'bar' } : { ...U; id: string; } | { ...T; ...U; id: string; } | { ...T; ...V; id: string; } | { ...U; ...V; id: string; } ->tu : any ->uv : any +>tu : T | U +>uv : U | V >id : string >'bar' : "bar" @@ -127,5 +127,3 @@ function iteratedDoubleUnion(t: T, u: U, v: V): void { >result : { ...U; id: string; } | { ...T; ...U; id: string; } | { ...T; ...V; id: string; } | { ...U; ...V; id: string; } } - - diff --git a/tests/baselines/reference/spreadInvalidArgumentType.errors.txt b/tests/baselines/reference/spreadInvalidArgumentType.errors.txt index 5088390f9eea9..116f5e9095abc 100644 --- a/tests/baselines/reference/spreadInvalidArgumentType.errors.txt +++ b/tests/baselines/reference/spreadInvalidArgumentType.errors.txt @@ -1,12 +1,4 @@ -tests/cases/compiler/spreadInvalidArgumentType.ts(31,16): error TS2698: Spread types may only be created from object types. -tests/cases/compiler/spreadInvalidArgumentType.ts(33,16): error TS2698: Spread types may only be created from object types. -tests/cases/compiler/spreadInvalidArgumentType.ts(35,16): error TS2698: Spread types may only be created from object types. tests/cases/compiler/spreadInvalidArgumentType.ts(36,16): error TS2698: Spread types may only be created from object types. -tests/cases/compiler/spreadInvalidArgumentType.ts(38,16): error TS2698: Spread types may only be created from object types. -tests/cases/compiler/spreadInvalidArgumentType.ts(41,16): error TS2698: Spread types may only be created from object types. -tests/cases/compiler/spreadInvalidArgumentType.ts(42,16): error TS2698: Spread types may only be created from object types. -tests/cases/compiler/spreadInvalidArgumentType.ts(44,17): error TS2698: Spread types may only be created from object types. -tests/cases/compiler/spreadInvalidArgumentType.ts(45,17): error TS2698: Spread types may only be created from object types. tests/cases/compiler/spreadInvalidArgumentType.ts(47,17): error TS2698: Spread types may only be created from object types. tests/cases/compiler/spreadInvalidArgumentType.ts(48,17): error TS2698: Spread types may only be created from object types. tests/cases/compiler/spreadInvalidArgumentType.ts(55,17): error TS2698: Spread types may only be created from object types. @@ -14,7 +6,7 @@ tests/cases/compiler/spreadInvalidArgumentType.ts(56,17): error TS2698: Spread t tests/cases/compiler/spreadInvalidArgumentType.ts(58,17): error TS2698: Spread types may only be created from object types. -==== tests/cases/compiler/spreadInvalidArgumentType.ts (14 errors) ==== +==== tests/cases/compiler/spreadInvalidArgumentType.ts (6 errors) ==== enum E { v1, v2 }; function f(p1: T, p2: T[]) { @@ -45,39 +37,23 @@ tests/cases/compiler/spreadInvalidArgumentType.ts(58,17): error TS2698: Spread t var e: E; - var o1 = { ...p1 }; // Error, generic type paramterre - ~~~~~ -!!! error TS2698: Spread types may only be created from object types. + var o1 = { ...p1 }; // OK, generic type parameter var o2 = { ...p2 }; // OK - var o3 = { ...t }; // Error, generic type paramter - ~~~~ -!!! error TS2698: Spread types may only be created from object types. + var o3 = { ...t }; // OK, generic type parameter - var o4 = { ...i }; // Error, index access - ~~~~ -!!! error TS2698: Spread types may only be created from object types. + var o4 = { ...i }; // OK, index access var o5 = { ...k }; // Error, index ~~~~ !!! error TS2698: Spread types may only be created from object types. - var o6 = { ...mapped_generic }; // Error, generic mapped object type - ~~~~~~~~~~~~~~~~~ -!!! error TS2698: Spread types may only be created from object types. + var o6 = { ...mapped_generic }; // OK, generic mapped object type var o7 = { ...mapped }; // OK, non-generic mapped type - var o8 = { ...union_generic }; // Error, union with generic type parameter - ~~~~~~~~~~~~~~~~ -!!! error TS2698: Spread types may only be created from object types. - var o9 = { ...union_primitive }; // Error, union with generic type parameter - ~~~~~~~~~~~~~~~~~~ -!!! error TS2698: Spread types may only be created from object types. + var o8 = { ...union_generic }; // OK, union with generic type parameter + var o9 = { ...union_primitive }; // OK, union with generic type parameter - var o10 = { ...intersection_generic }; // Error, intersection with generic type parameter - ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2698: Spread types may only be created from object types. - var o11 = { ...intersection_premitive }; // Error, intersection with generic type parameter - ~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2698: Spread types may only be created from object types. + var o10 = { ...intersection_generic }; // OK, intersection with generic type parameter + var o11 = { ...intersection_premitive }; // OK, intersection with generic type parameter var o12 = { ...num }; // Error ~~~~~~ @@ -101,4 +77,5 @@ tests/cases/compiler/spreadInvalidArgumentType.ts(58,17): error TS2698: Spread t var o19 = { ...e }; // Error, enum ~~~~ !!! error TS2698: Spread types may only be created from object types. - } \ No newline at end of file + } + \ No newline at end of file diff --git a/tests/baselines/reference/spreadInvalidArgumentType.js b/tests/baselines/reference/spreadInvalidArgumentType.js index 26f958f224da3..3490d1300a63f 100644 --- a/tests/baselines/reference/spreadInvalidArgumentType.js +++ b/tests/baselines/reference/spreadInvalidArgumentType.js @@ -29,21 +29,21 @@ function f(p1: T, p2: T[]) { var e: E; - var o1 = { ...p1 }; // Error, generic type paramterre + var o1 = { ...p1 }; // OK, generic type parameter var o2 = { ...p2 }; // OK - var o3 = { ...t }; // Error, generic type paramter + var o3 = { ...t }; // OK, generic type parameter - var o4 = { ...i }; // Error, index access + var o4 = { ...i }; // OK, index access var o5 = { ...k }; // Error, index - var o6 = { ...mapped_generic }; // Error, generic mapped object type + var o6 = { ...mapped_generic }; // OK, generic mapped object type var o7 = { ...mapped }; // OK, non-generic mapped type - var o8 = { ...union_generic }; // Error, union with generic type parameter - var o9 = { ...union_primitive }; // Error, union with generic type parameter + var o8 = { ...union_generic }; // OK, union with generic type parameter + var o9 = { ...union_primitive }; // OK, union with generic type parameter - var o10 = { ...intersection_generic }; // Error, intersection with generic type parameter - var o11 = { ...intersection_premitive }; // Error, intersection with generic type parameter + var o10 = { ...intersection_generic }; // OK, intersection with generic type parameter + var o11 = { ...intersection_premitive }; // OK, intersection with generic type parameter var o12 = { ...num }; // Error var o13 = { ...str }; // Error @@ -57,7 +57,8 @@ function f(p1: T, p2: T[]) { var o18 = { ...literal_number }; // Error var o19 = { ...e }; // Error, enum -} +} + //// [spreadInvalidArgumentType.js] var __assign = (this && this.__assign) || Object.assign || function(t) { @@ -92,17 +93,17 @@ function f(p1, p2) { var literal_string; var literal_number; var e; - var o1 = __assign({}, p1); // Error, generic type paramterre + var o1 = __assign({}, p1); // OK, generic type parameter var o2 = __assign({}, p2); // OK - var o3 = __assign({}, t); // Error, generic type paramter - var o4 = __assign({}, i); // Error, index access + var o3 = __assign({}, t); // OK, generic type parameter + var o4 = __assign({}, i); // OK, index access var o5 = __assign({}, k); // Error, index - var o6 = __assign({}, mapped_generic); // Error, generic mapped object type + var o6 = __assign({}, mapped_generic); // OK, generic mapped object type var o7 = __assign({}, mapped); // OK, non-generic mapped type - var o8 = __assign({}, union_generic); // Error, union with generic type parameter - var o9 = __assign({}, union_primitive); // Error, union with generic type parameter - var o10 = __assign({}, intersection_generic); // Error, intersection with generic type parameter - var o11 = __assign({}, intersection_premitive); // Error, intersection with generic type parameter + var o8 = __assign({}, union_generic); // OK, union with generic type parameter + var o9 = __assign({}, union_primitive); // OK, union with generic type parameter + var o10 = __assign({}, intersection_generic); // OK, intersection with generic type parameter + var o11 = __assign({}, intersection_premitive); // OK, intersection with generic type parameter var o12 = __assign({}, num); // Error var o13 = __assign({}, str); // Error var o14 = __assign({}, u); // OK diff --git a/tests/cases/compiler/spreadInvalidArgumentType.ts b/tests/cases/compiler/spreadInvalidArgumentType.ts index 2ac6aa921f48c..8e188626200dd 100644 --- a/tests/cases/compiler/spreadInvalidArgumentType.ts +++ b/tests/cases/compiler/spreadInvalidArgumentType.ts @@ -28,21 +28,21 @@ function f(p1: T, p2: T[]) { var e: E; - var o1 = { ...p1 }; // Error, generic type paramterre + var o1 = { ...p1 }; // OK, generic type parameter var o2 = { ...p2 }; // OK - var o3 = { ...t }; // Error, generic type paramter + var o3 = { ...t }; // OK, generic type parameter - var o4 = { ...i }; // Error, index access + var o4 = { ...i }; // OK, index access var o5 = { ...k }; // Error, index - var o6 = { ...mapped_generic }; // Error, generic mapped object type + var o6 = { ...mapped_generic }; // OK, generic mapped object type var o7 = { ...mapped }; // OK, non-generic mapped type - var o8 = { ...union_generic }; // Error, union with generic type parameter - var o9 = { ...union_primitive }; // Error, union with generic type parameter + var o8 = { ...union_generic }; // OK, union with generic type parameter + var o9 = { ...union_primitive }; // OK, union with generic type parameter - var o10 = { ...intersection_generic }; // Error, intersection with generic type parameter - var o11 = { ...intersection_premitive }; // Error, intersection with generic type parameter + var o10 = { ...intersection_generic }; // OK, intersection with generic type parameter + var o11 = { ...intersection_premitive }; // OK, intersection with generic type parameter var o12 = { ...num }; // Error var o13 = { ...str }; // Error @@ -56,4 +56,4 @@ function f(p1: T, p2: T[]) { var o18 = { ...literal_number }; // Error var o19 = { ...e }; // Error, enum -} \ No newline at end of file +} diff --git a/tests/cases/conformance/types/spread/interfaceSpread.ts b/tests/cases/conformance/types/spread/interfaceSpread.ts new file mode 100644 index 0000000000000..e49fe412cecd3 --- /dev/null +++ b/tests/cases/conformance/types/spread/interfaceSpread.ts @@ -0,0 +1,8 @@ +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 ebf2bdb2adede..de2e49e676a39 100644 --- a/tests/cases/conformance/types/spread/objectSpread.ts +++ b/tests/cases/conformance/types/spread/objectSpread.ts @@ -35,7 +35,9 @@ let getter: { a: number, c: number } = { ...op, c: 7 } getter.a = 12; -// functions result in { } +// null, undefined and functions result in { } +let spreadNull = { ...null }; +let spreadUndefined = { ...undefined }; let spreadFunc = { ...(function () { }) }; // any results in any @@ -79,3 +81,20 @@ 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 new file mode 100644 index 0000000000000..8fa6363d2efca --- /dev/null +++ b/tests/cases/conformance/types/spread/objectSpreadGeneric.ts @@ -0,0 +1,72 @@ +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 ae46f2547d54c..0f3555528d734 100644 --- a/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts +++ b/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts @@ -1,3 +1,11 @@ +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; @@ -8,9 +16,13 @@ interface Indexed2 { } let indexed: Indexed; let indexed2: Indexed2; -let i = { ...indexed, b: 11 }; +let i: { ...Indexed, b: number }; // only indexed has indexer, so i[101]: any i[101]; -let ii = { ...indexed, ...indexed2 }; +let ii: { ...Indexed, ...Indexed2, b: boolean, d: number }; // both have indexer, so i[1001]: number | boolean -ii[1001]; +let nb: number | boolean = ii[1001]; + +function f(t: T) { + let i: { ...T, [n: number]: string }; +} diff --git a/tests/cases/conformance/types/spread/objectSpreadInference.ts b/tests/cases/conformance/types/spread/objectSpreadInference.ts new file mode 100644 index 0000000000000..a9c11187cca6a --- /dev/null +++ b/tests/cases/conformance/types/spread/objectSpreadInference.ts @@ -0,0 +1,19 @@ +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 new file mode 100644 index 0000000000000..479faf13d0809 --- /dev/null +++ b/tests/cases/conformance/types/spread/objectSpreadIntersection.ts @@ -0,0 +1,35 @@ +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 6d1e0dde42900..17cb0f29a3b7d 100644 --- a/tests/cases/conformance/types/spread/objectSpreadNegative.ts +++ b/tests/cases/conformance/types/spread/objectSpreadNegative.ts @@ -8,9 +8,7 @@ class PrivateOptionalX { class PublicX { public x: number; } -let publicX: PublicX; -let privateOptionalX: PrivateOptionalX; -let o2 = { ...publicX, ...privateOptionalX }; +let o2: { ...PublicX, ...PrivateOptionalX }; let sn: number = o2.x; // error, x is private let optionalString: { sn?: string }; let optionalNumber: { sn?: number }; @@ -20,15 +18,20 @@ let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumbe // assignability as target interface Bool { b: boolean }; interface Str { s: string }; -let spread = { ...{ b: true }, ...{s: "foo" } }; -spread = { s: "foo" }; // error, missing 'b' -let b = { b: false }; +let spread: { ...Bool, ...Str } = { s: "foo" }; // error, missing 'b' +let b: Bool; 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 are not allowed let spreadNum = { ...12 }; let spreadSum = { ...1 + 1 }; @@ -52,18 +55,14 @@ let c: C = new C() let spreadC = { ...c } spreadC.m(); // error 'm' is not in '{ ... c }' -// generics -function f(t: T, u: U) { - return { ...t, ...u, id: 'id' }; -} -function override(initial: U, override: U): U { +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 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 new file mode 100644 index 0000000000000..1db930cb71c51 --- /dev/null +++ b/tests/cases/conformance/types/spread/objectSpreadScenarios.ts @@ -0,0 +1,17 @@ +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 new file mode 100644 index 0000000000000..6f6cb1954ec61 --- /dev/null +++ b/tests/cases/conformance/types/spread/objectSpreadUnion.ts @@ -0,0 +1,21 @@ +// 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 05c83491f6651..650324a5d8467 100644 --- a/tests/cases/fourslash/findAllRefsForObjectSpread.ts +++ b/tests/cases/fourslash/findAllRefsForObjectSpread.ts @@ -2,9 +2,7 @@ ////interface A1 { [|a|]: string }; ////interface A2 { [|a|]?: number }; -////let a1: A1; -////let a2: A2; -////let a12 = { ...a1, ...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 b23d0a8044832..64623c36cb76b 100644 --- a/tests/cases/fourslash/goToDefinitionObjectSpread.ts +++ b/tests/cases/fourslash/goToDefinitionObjectSpread.ts @@ -2,8 +2,6 @@ ////interface A1 { /*1*/a: number }; ////interface A2 { /*2*/a?: number }; -////let a1: A1; -////let a2: A2; -////let a12 = { ...a1, ...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 eba148c0e3944..a2c640361e59c 100644 --- a/tests/cases/fourslash/renameObjectSpread.ts +++ b/tests/cases/fourslash/renameObjectSpread.ts @@ -2,9 +2,7 @@ ////interface A1 { [|a|]: number }; ////interface A2 { [|a|]?: number }; -////let a1: A1; -////let a2: A2; -////let a12 = { ...a1, ...a2 }; +////let a12: { ...A1, ...A2 }; ////a12.[|a|]; const ranges = test.ranges(); verify.assertHasRanges(ranges); From 268969bfc390c5f906f9b1017280f056439b4fd9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 12 Jan 2017 12:51:37 -0800 Subject: [PATCH 4/9] Change spread type syntax to `spread(T, U)` `spread(T)` is also allowed, for unary spreads --- src/compiler/checker.ts | 149 +++++++-------------------- src/compiler/declarationEmitter.ts | 14 +-- src/compiler/diagnosticMessages.json | 8 -- src/compiler/parser.ts | 54 +++++----- src/compiler/scanner.ts | 1 + src/compiler/types.ts | 14 +-- src/lib/es2015.core.d.ts | 6 +- 7 files changed, 88 insertions(+), 158 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2681225618047..7af0fe039b59c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2440,45 +2440,25 @@ namespace ts { } } - function writeSpreadType(type: SpreadType) { - writePunctuation(writer, SyntaxKind.OpenBraceToken); - writer.writeLine(); - writer.increaseIndent(); - - writeSpreadTypeWorker(type, /*atEnd*/true); - - writer.decreaseIndent(); - writePunctuation(writer, SyntaxKind.CloseBraceToken); - } - - function writeSpreadTypeWorker(type: SpreadType, atEnd: boolean): void { - if (type.left.flags & TypeFlags.Spread) { - writeSpreadTypeWorker(type.left as SpreadType, /*atEnd*/false); - } - else { - const saveInObjectTypeLiteral = inObjectTypeLiteral; - inObjectTypeLiteral = true; - writeObjectLiteralType(resolveStructuredTypeMembers(type.left as ResolvedType)); - inObjectTypeLiteral = saveInObjectTypeLiteral; - } - if (type.right.flags & TypeFlags.Object) { - // if type.right is an object 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; + function writeSpreadType(type: SpreadType, nested?: boolean) { + if (nested && type.left === emptyObjectType) { + writeType(type.right, TypeFormatFlags.None); } else { - writePunctuation(writer, SyntaxKind.DotDotDotToken); - writeType(type.right, TypeFormatFlags.None); - if (atEnd) { + writer.writeKeyword("spread"); + writePunctuation(writer, SyntaxKind.OpenParenToken); + if (type.left !== emptyObjectType) { + if (type.left.flags & TypeFlags.Spread) { + writeSpreadType(type.left as SpreadType, /*nested*/ true); + } + else { + writeType(type.left, TypeFormatFlags.None); + } + writePunctuation(writer, SyntaxKind.CommaToken); writeSpace(writer); } - else { - writePunctuation(writer, SyntaxKind.SemicolonToken); - writer.writeLine(); - } + writeType(type.right, TypeFormatFlags.None); + writePunctuation(writer, SyntaxKind.CloseParenToken); } } @@ -6080,6 +6060,16 @@ namespace ts { return links.resolvedType; } + function getTypeFromSpreadTypeNode(node: SpreadTypeNode): Type { + const links = getNodeLinks(node); + if (!links.resolvedType) { + links.resolvedType = getSpreadType( + node.right ? getTypeFromTypeNode(node.left) : emptyObjectType, + getTypeFromTypeNode(node.right || node.left)); + } + return links.resolvedType; + } + function getIndexTypeForGenericType(type: TypeVariable | UnionOrIntersectionType) { if (!type.resolvedIndexType) { type.resolvedIndexType = createType(TypeFlags.Index); @@ -6264,12 +6254,6 @@ namespace ts { function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: TypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - const hasSpread = (node.kind === SyntaxKind.TypeLiteral && - find((node as TypeLiteralNode).members, elt => elt.kind === SyntaxKind.SpreadTypeAssignment)); - if (hasSpread) { - return getTypeFromSpreadTypeLiteral(node as TypeLiteralNode); - } - // Deferred resolution of members is handled by resolveObjectTypeMembers const aliasSymbol = getAliasSymbolForTypeNode(node); if (isEmpty(node.symbol.members) && !aliasSymbol) { @@ -6285,50 +6269,6 @@ namespace ts { return links.resolvedType; } - function getTypeFromSpreadTypeLiteral(node: TypeLiteralNode): Type { - let spread: Type = emptyObjectType; - let members: Map; - let stringIndexInfo: IndexInfo; - let numberIndexInfo: IndexInfo; - for (const member of node.members) { - if (member.kind === SyntaxKind.SpreadTypeAssignment) { - if (members) { - const type = createAnonymousType(node.symbol, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - spread = getSpreadType(spread, type); - members = undefined; - stringIndexInfo = undefined; - numberIndexInfo = undefined; - } - const type = getTypeFromTypeNode((member as SpreadTypeAssignment).type); - spread = getSpreadType(spread, type); - } - 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 = getTypeFromTypeNode((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); - } - if (spread.flags & TypeFlags.Object) { - // only set the symbol if this is a (fresh) object type - spread.symbol = node.symbol; - } - return spread; - } - function getAliasSymbolForTypeNode(node: TypeNode) { return node.parent.kind === SyntaxKind.TypeAliasDeclaration ? getSymbolOfNode(node.parent) : undefined; } @@ -6339,9 +6279,9 @@ namespace ts { } /** - * Since the source of spread types are object 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. + * Since spread types are binary and object literals are not, + * checkObjectLiteral calls getSpreadType in a left-folding way. + * If a nested spread type literal is not left-deep, getSpreadType will transform it to left-deep form. * * If getSpreadType returns a spread type, the following properties hold: * 1. Left-deep: spread.left is always another spread type (the recursive case) @@ -6394,6 +6334,10 @@ namespace ts { return left; } + if (!(left.flags & (TypeFlags.Spread | TypeFlags.Object))) { + // put an emptyObjectType terminator on the left + left = getSpreadType(emptyObjectType, left); + } const simplified = simplifySpreadType(left, right); if (simplified) { return simplified; @@ -6403,8 +6347,6 @@ namespace ts { return createSpreadType(left, right); } 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.left = left as SpreadType | ResolvedType; spread.right = right as TypeParameter | IntersectionType | IndexType | IndexedAccessType | ResolvedType; return spread; @@ -6646,6 +6588,8 @@ namespace ts { return getTypeFromUnionTypeNode(node); case SyntaxKind.IntersectionType: return getTypeFromIntersectionTypeNode(node); + case SyntaxKind.SpreadType: + return getTypeFromSpreadTypeNode(node as SpreadTypeNode); case SyntaxKind.ParenthesizedType: case SyntaxKind.JSDocNullableType: case SyntaxKind.JSDocNonNullableType: @@ -7687,8 +7631,7 @@ namespace ts { } else if (target.flags & TypeFlags.Spread) { // T is assignable to ...T - if (source.symbol === (target as SpreadType).right.symbol - && (target as SpreadType).left === emptyObjectType) { + if (source === (target as SpreadType).right && (target as SpreadType).left === emptyObjectType) { return Ternary.True; } } @@ -16265,19 +16208,10 @@ namespace ts { function checkTypeLiteral(node: TypeLiteralNode) { forEach(node.members, checkSourceElement); if (produceDiagnostics) { - if (find(node.members, p => p.kind === SyntaxKind.SpreadTypeAssignment)) { - 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_constructor_signatures); - } - } - else { - const type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); - checkIndexConstraints(type); - checkTypeForDuplicateIndexSignatures(node); - checkObjectTypeForDuplicateDeclarations(node); - } + const type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); + checkIndexConstraints(type); + checkTypeForDuplicateIndexSignatures(node); + checkObjectTypeForDuplicateDeclarations(node); } } @@ -21660,11 +21594,6 @@ namespace ts { } } - let result: TypeElement; - if (result = find(node.members, e => e.kind === SyntaxKind.SpreadTypeAssignment)) { - 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 b023d33c9717a..2372069a4a0c0 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -412,6 +412,8 @@ namespace ts { return emitUnionType(type); case SyntaxKind.IntersectionType: return emitIntersectionType(type); + case SyntaxKind.SpreadType: + return emitSpreadType(type as SpreadTypeNode); case SyntaxKind.ParenthesizedType: return emitParenType(type); case SyntaxKind.TypeOperator: @@ -1174,10 +1176,12 @@ namespace ts { writeLine(); } - function emitSpreadTypeAssignment(type: SpreadTypeAssignment) { - write("..."); - emitType(type.type); - write(";"); + function emitSpreadType(type: SpreadTypeNode) { + write("spread("); + emitType(type.left); + write(",") + emitType(type.right); + write(")"); writeLine(); } @@ -1771,8 +1775,6 @@ namespace ts { case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: return emitPropertyDeclaration(node); - case SyntaxKind.SpreadTypeAssignment: - return emitSpreadTypeAssignment(node as SpreadTypeAssignment); case SyntaxKind.EnumMember: return emitEnumMemberDeclaration(node); case SyntaxKind.ExportAssignment: diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 1190ee99a88dd..52fc401d1f151 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2015,10 +2015,6 @@ "category": "Error", "code": 2698 }, - "Type literals with spreads cannot contain index, call or constructor signatures.": { - "category": "Error", - "code": 2699 - }, "Rest types may only be created from object types.": { "category": "Error", "code": 2700 @@ -2039,10 +2035,6 @@ "category": "Error", "code": 2704 }, - "Interface declaration cannot contain a spread property.": { - "category": "Error", - "code": 2705 - }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 69690d2a7f082..09bdab6936dd5 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -76,8 +76,9 @@ namespace ts { visitNode(cbNode, (node).objectAssignmentInitializer); case SyntaxKind.SpreadAssignment: return visitNode(cbNode, (node).expression); - case SyntaxKind.SpreadTypeAssignment: - return visitNode(cbNode, (node as SpreadTypeAssignment).type); + case SyntaxKind.SpreadType: + return visitNode(cbNode, (node as SpreadTypeNode).left) || + visitNode(cbNode, (node as SpreadTypeNode).right); case SyntaxKind.Parameter: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -2377,9 +2378,6 @@ namespace ts { if (token() === SyntaxKind.OpenBracketToken) { return true; } - if (token() === SyntaxKind.DotDotDotToken) { - return true; - } // Try to get the first property-like token following all modifiers if (isLiteralPropertyName()) { idToken = token(); @@ -2399,17 +2397,11 @@ namespace ts { } function parseTypeMember(): TypeElement { - switch (token()) { - case SyntaxKind.OpenParenToken: - case SyntaxKind.LessThanToken: - return parseSignatureMember(SyntaxKind.CallSignature); - case SyntaxKind.NewKeyword: - if (lookAhead(isStartOfConstructSignature)) { - return parseSignatureMember(SyntaxKind.ConstructSignature); - } - break; - case SyntaxKind.DotDotDotToken: - return parseSpreadTypeAssignment(); + if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { + return parseSignatureMember(SyntaxKind.CallSignature); + } + if (token() === SyntaxKind.NewKeyword && lookAhead(isStartOfConstructSignature)) { + return parseSignatureMember(SyntaxKind.ConstructSignature); } const fullStart = getNodePos(); const modifiers = parseModifiers(); @@ -2419,14 +2411,6 @@ namespace ts { return parsePropertyOrMethodSignature(fullStart, modifiers); } - function parseSpreadTypeAssignment() { - const element = createNode(SyntaxKind.SpreadTypeAssignment, scanner.getStartPos()) as SpreadTypeAssignment; - parseTokenNode(); // parse `...` - element.type = parseType(); - parseTypeMemberSemicolon(); - return finishNode(element); - } - function isStartOfConstructSignature() { nextToken(); return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken; @@ -2626,6 +2610,26 @@ namespace ts { return type; } + function parseSpreadType(): TypeNode { + const node = createNode(SyntaxKind.SpreadType) as SpreadTypeNode; + parseExpected(SyntaxKind.SpreadKeyword); + parseExpected(SyntaxKind.OpenParenToken); + node.left = parseType(); + if(parseOptional(SyntaxKind.CommaToken)) { + node.right = parseType(); + } + parseExpected(SyntaxKind.CloseParenToken); + return finishNode(node); + } + + function parseSpreadTypeOrHigher() { + switch (token()) { + case SyntaxKind.SpreadKeyword: + return parseSpreadType(); + } + return parseArrayTypeOrHigher(); + } + function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword) { const node = createNode(SyntaxKind.TypeOperator); parseExpected(operator); @@ -2639,7 +2643,7 @@ namespace ts { case SyntaxKind.KeyOfKeyword: return parseTypeOperator(SyntaxKind.KeyOfKeyword); } - return parseArrayTypeOrHigher(); + return parseSpreadTypeOrHigher(); } function parseUnionOrIntersectionType(kind: SyntaxKind, parseConstituentType: () => TypeNode, operator: SyntaxKind): TypeNode { diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index a03bf733f75c9..7347895a1e2f8 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -108,6 +108,7 @@ namespace ts { "global": SyntaxKind.GlobalKeyword, "return": SyntaxKind.ReturnKeyword, "set": SyntaxKind.SetKeyword, + "spread": SyntaxKind.SpreadKeyword, "static": SyntaxKind.StaticKeyword, "string": SyntaxKind.StringKeyword, "super": SyntaxKind.SuperKeyword, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 68d578c24337a..dd4ff01bcd810 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -169,6 +169,7 @@ namespace ts { GetKeyword, IsKeyword, KeyOfKeyword, + SpreadKeyword, ModuleKeyword, NamespaceKeyword, NeverKeyword, @@ -216,6 +217,7 @@ namespace ts { TupleType, UnionType, IntersectionType, + SpreadType, ParenthesizedType, ThisType, TypeOperator, @@ -324,7 +326,6 @@ namespace ts { PropertyAssignment, ShorthandPropertyAssignment, SpreadAssignment, - SpreadTypeAssignment, // Enum EnumMember, @@ -665,11 +666,6 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface SpreadTypeAssignment extends TypeElement { - kind: SyntaxKind.SpreadTypeAssignment; - type: TypeNode; - } - export interface PropertyDeclaration extends ClassElement { kind: SyntaxKind.PropertyDeclaration; questionToken?: QuestionToken; // Present for use with reporting a grammar error @@ -892,6 +888,12 @@ namespace ts { kind: SyntaxKind.IntersectionType; } + export interface SpreadTypeNode extends TypeNode { + kind: SyntaxKind.SpreadType; + left: TypeNode; + right?: TypeNode; + } + export interface ParenthesizedTypeNode extends TypeNode { kind: SyntaxKind.ParenthesizedType; type: TypeNode; diff --git a/src/lib/es2015.core.d.ts b/src/lib/es2015.core.d.ts index 73c71b3d6226c..5d46a11369c52 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): spread(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): spread(spread(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): spread(spread(spread(T, U), V), W); /** * Copy the values of all of the enumerable own properties from one or more source objects to a From 9f1c1b709134fc7dbecfe2de5c331552ac905b97 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 12 Jan 2017 12:52:17 -0800 Subject: [PATCH 5/9] Update tests with new spread type syntax --- .../reference/interfaceSpread.errors.txt | 21 --- tests/baselines/reference/interfaceSpread.js | 15 -- tests/baselines/reference/objectSpread.js | 4 +- .../baselines/reference/objectSpread.symbols | 8 +- tests/baselines/reference/objectSpread.types | 18 +- .../reference/objectSpreadGeneric.errors.txt | 158 +++++++++--------- .../reference/objectSpreadGeneric.js | 52 +++--- .../objectSpreadIndexSignature.errors.txt | 38 ----- .../reference/objectSpreadIndexSignature.js | 8 +- .../objectSpreadIndexSignature.symbols | 87 ++++++++++ .../objectSpreadIndexSignature.types | 93 +++++++++++ .../reference/objectSpreadInference.js | 4 +- .../reference/objectSpreadInference.symbols | 28 ++-- .../reference/objectSpreadInference.types | 20 +-- .../reference/objectSpreadIntersection.js | 10 +- .../objectSpreadIntersection.symbols | 20 +-- .../reference/objectSpreadIntersection.types | 42 ++--- .../reference/objectSpreadNegative.errors.txt | 26 ++- .../reference/objectSpreadNegative.js | 10 +- .../reference/objectSpreadScenarios.js | 6 +- .../reference/objectSpreadScenarios.symbols | 10 +- .../reference/objectSpreadScenarios.types | 52 +++--- .../baselines/reference/objectSpreadUnion.js | 10 +- .../reference/objectSpreadUnion.symbols | 30 ++-- .../reference/objectSpreadUnion.types | 32 ++-- tests/baselines/reference/spreadLeftDeep.js | 16 ++ .../reference/spreadLeftDeep.symbols | 29 ++++ .../baselines/reference/spreadLeftDeep.types | 29 ++++ .../types/spread/interfaceSpread.ts | 8 - .../conformance/types/spread/objectSpread.ts | 4 +- .../types/spread/objectSpreadGeneric.ts | 52 +++--- .../spread/objectSpreadIndexSignature.ts | 8 +- .../types/spread/objectSpreadInference.ts | 4 +- .../types/spread/objectSpreadIntersection.ts | 10 +- .../types/spread/objectSpreadNegative.ts | 10 +- .../types/spread/objectSpreadScenarios.ts | 6 +- .../types/spread/objectSpreadUnion.ts | 10 +- .../types/spread/spreadLeftDeep.ts | 6 + .../fourslash/findAllRefsForObjectSpread.ts | 2 +- .../fourslash/goToDefinitionObjectSpread.ts | 2 +- tests/cases/fourslash/renameObjectSpread.ts | 2 +- 41 files changed, 586 insertions(+), 414 deletions(-) delete mode 100644 tests/baselines/reference/interfaceSpread.errors.txt delete mode 100644 tests/baselines/reference/interfaceSpread.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 create mode 100644 tests/baselines/reference/spreadLeftDeep.js create mode 100644 tests/baselines/reference/spreadLeftDeep.symbols create mode 100644 tests/baselines/reference/spreadLeftDeep.types delete mode 100644 tests/cases/conformance/types/spread/interfaceSpread.ts create mode 100644 tests/cases/conformance/types/spread/spreadLeftDeep.ts diff --git a/tests/baselines/reference/interfaceSpread.errors.txt b/tests/baselines/reference/interfaceSpread.errors.txt deleted file mode 100644 index 9fc456c5567f0..0000000000000 --- a/tests/baselines/reference/interfaceSpread.errors.txt +++ /dev/null @@ -1,21 +0,0 @@ -tests/cases/conformance/types/spread/interfaceSpread.ts(2,5): error TS2705: Interface declaration cannot contain a spread property. -tests/cases/conformance/types/spread/interfaceSpread.ts(7,10): error TS2339: Property 'jam' does not exist on type 'Congealed<{ jam: number; }, { peanutButter: number; }>'. -tests/cases/conformance/types/spread/interfaceSpread.ts(8,10): error TS2339: Property 'peanutButter' does not exist on type 'Congealed<{ jam: number; }, { peanutButter: number; }>'. - - -==== tests/cases/conformance/types/spread/interfaceSpread.ts (3 errors) ==== - interface Congealed { - ...T - ~~~~ -!!! error TS2705: Interface declaration cannot contain a spread property. - ...U - } - - let sandwich: Congealed<{ jam: number }, { peanutButter: number }>; - sandwich.jam; - ~~~ -!!! error TS2339: Property 'jam' does not exist on type 'Congealed<{ jam: number; }, { peanutButter: number; }>'. - sandwich.peanutButter; - ~~~~~~~~~~~~ -!!! error TS2339: Property 'peanutButter' does not exist on type 'Congealed<{ jam: number; }, { peanutButter: number; }>'. - \ No newline at end of file diff --git a/tests/baselines/reference/interfaceSpread.js b/tests/baselines/reference/interfaceSpread.js deleted file mode 100644 index cd01674884caa..0000000000000 --- a/tests/baselines/reference/interfaceSpread.js +++ /dev/null @@ -1,15 +0,0 @@ -//// [interfaceSpread.ts] -interface Congealed { - ...T - ...U -} - -let sandwich: Congealed<{ jam: number }, { peanutButter: number }>; -sandwich.jam; -sandwich.peanutButter; - - -//// [interfaceSpread.js] -var sandwich; -sandwich.jam; -sandwich.peanutButter; diff --git a/tests/baselines/reference/objectSpread.js b/tests/baselines/reference/objectSpread.js index b9bfb19d633ab..7247b4fcc8ae8 100644 --- a/tests/baselines/reference/objectSpread.js +++ b/tests/baselines/reference/objectSpread.js @@ -82,7 +82,7 @@ let a = 12; let shortCutted: { a: number, b: string } = { ...o, a } // generics -function f(t: T, u: U): { ...T, ...U, id: string } { +function f(t: T, u: U): spread(spread(T, U), { id: string }) { return { ...t, ...u, id: 'id' }; } @@ -96,7 +96,7 @@ 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 } = +let classesAreWrong: spread(spread({ id: string }, C), D) = f(new C(), new D()) diff --git a/tests/baselines/reference/objectSpread.symbols b/tests/baselines/reference/objectSpread.symbols index 7d5b8a527706c..8cae570e47275 100644 --- a/tests/baselines/reference/objectSpread.symbols +++ b/tests/baselines/reference/objectSpread.symbols @@ -324,7 +324,7 @@ let shortCutted: { a: number, b: string } = { ...o, a } >a : Symbol(a, Decl(objectSpread.ts, 80, 51)) // generics -function f(t: T, u: U): { ...T, ...U, id: string } { +function f(t: T, u: U): spread(spread(T, U), { id: string }) { >f : Symbol(f, Decl(objectSpread.ts, 80, 55)) >T : Symbol(T, Decl(objectSpread.ts, 83, 11)) >U : Symbol(U, Decl(objectSpread.ts, 83, 13)) @@ -334,7 +334,7 @@ function f(t: T, u: U): { ...T, ...U, id: string } { >U : Symbol(U, Decl(objectSpread.ts, 83, 13)) >T : Symbol(T, Decl(objectSpread.ts, 83, 11)) >U : Symbol(U, Decl(objectSpread.ts, 83, 13)) ->id : Symbol(id, Decl(objectSpread.ts, 83, 43)) +>id : Symbol(id, Decl(objectSpread.ts, 83, 52)) return { ...t, ...u, id: 'id' }; >t : Symbol(t, Decl(objectSpread.ts, 83, 17)) @@ -398,9 +398,9 @@ class D { m() { }; q = 2; } >m : Symbol(D.m, Decl(objectSpread.ts, 96, 9)) >q : Symbol(D.q, Decl(objectSpread.ts, 96, 18)) -let classesAreWrong: { id: string, ...C, ...D } = +let classesAreWrong: spread(spread({ id: string }, C), D) = >classesAreWrong : Symbol(classesAreWrong, Decl(objectSpread.ts, 97, 3)) ->id : Symbol(id, Decl(objectSpread.ts, 97, 22)) +>id : Symbol(id, Decl(objectSpread.ts, 97, 36)) >C : Symbol(C, Decl(objectSpread.ts, 43, 32)) >D : Symbol(D, Decl(objectSpread.ts, 94, 44)) diff --git a/tests/baselines/reference/objectSpread.types b/tests/baselines/reference/objectSpread.types index 2e4c82bb8a6b2..e53474ced6235 100644 --- a/tests/baselines/reference/objectSpread.types +++ b/tests/baselines/reference/objectSpread.types @@ -418,8 +418,8 @@ let shortCutted: { a: number, b: string } = { ...o, a } >a : number // generics -function f(t: T, u: U): { ...T, ...U, id: string } { ->f : (t: T, u: U) => { ...T; ...U; id: string; } +function f(t: T, u: U): spread(spread(T, U), { id: string }) { +>f : (t: T, u: U) => spread(spread(T, U), { id: string; }) >T : T >U : U >t : T @@ -431,7 +431,7 @@ function f(t: T, u: U): { ...T, ...U, id: string } { >id : string return { ...t, ...u, id: 'id' }; ->{ ...t, ...u, id: 'id' } : { ...T; ...U; id: string; } +>{ ...t, ...u, id: 'id' } : spread(spread(T, U), { id: string; }) >t : T >u : U >id : string @@ -448,7 +448,7 @@ let exclusive: { 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; } +>f : (t: T, u: U) => spread(spread(T, U), { id: string; }) >{ a: 1, b: 'yes' } : { a: number; b: string; } >a : number >1 : 1 @@ -468,7 +468,7 @@ let overlap: { 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; } +>f : (t: T, u: U) => spread(spread(T, U), { id: string; }) >{ a: 1 } : { a: number; } >a : number >1 : 1 @@ -485,7 +485,7 @@ let overlapConflict: { 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; } +>f : (t: T, u: U) => spread(spread(T, U), { id: string; }) >{ a: 1 } : { a: number; } >a : number >1 : 1 @@ -502,7 +502,7 @@ let overwriteId: { 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; } +>f : (t: T, u: U) => spread(spread(T, U), { id: string; }) >{ a: 1, id: true } : { a: number; id: true; } >a : number >1 : 1 @@ -520,7 +520,7 @@ class D { m() { }; q = 2; } >q : number >2 : 2 -let classesAreWrong: { id: string, ...C, ...D } = +let classesAreWrong: spread(spread({ id: string }, C), D) = >classesAreWrong : { q: number; p: number; id: string; } >id : string >C : C @@ -528,7 +528,7 @@ let classesAreWrong: { id: string, ...C, ...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; } +>f : (t: T, u: U) => spread(spread(T, U), { id: string; }) >new C() : C >C : typeof C >new D() : D diff --git a/tests/baselines/reference/objectSpreadGeneric.errors.txt b/tests/baselines/reference/objectSpreadGeneric.errors.txt index d722ca316c245..4e0d30d896f4a 100644 --- a/tests/baselines/reference/objectSpreadGeneric.errors.txt +++ b/tests/baselines/reference/objectSpreadGeneric.errors.txt @@ -1,148 +1,148 @@ -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 TS90010: Type '{ first: string; ...T; ...U }' is not assignable to type '{ first: string; ...T; ...U }'. Two different types with this name exist, but they are unrelated. -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 TS90010: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. Two different types with this name exist, but they are unrelated. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(34,15): 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,15): error TS90010: 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; }'. Two different types with this name exist, but they are unrelated. -tests/cases/conformance/types/spread/objectSpreadGeneric.ts(38,15): 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,15): 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,15): 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(9,5): error TS2322: Type 'spread(U)' is not assignable to type 'U'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(10,11): error TS2322: Type 'spread(spread(T, U), V)' is not assignable to type 'spread(spread(V, U), T)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(11,11): error TS2322: Type 'spread(spread(T, U), V)' is not assignable to type 'spread(spread(U, T), V)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(12,11): error TS2322: Type 'spread(spread(T, U), V)' is not assignable to type 'spread(U, V)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(13,11): error TS2322: Type 'spread(spread(T, U), V)' is not assignable to type 'spread(T, V)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(14,11): error TS2322: Type 'spread(spread(T, U), V)' is not assignable to type 'spread(T, U)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(16,11): error TS90010: Type 'spread(spread({ first: string; }, T), U)' is not assignable to type 'spread(spread({ first: string; }, T), U)'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(19,11): error TS2322: Type '{}' is not assignable to type 'spread(T, U)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(26,11): error TS2322: Type 'spread(spread({ sn?: boolean; }, T), { sn?: string | number; })' is not assignable to type 'spread(T, { sn?: string | number | boolean; })'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(32,11): error TS90010: Type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; })' is not assignable to type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; })'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(34,11): error TS2322: Type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; })' is not assignable to type 'spread(spread({ first: string; second: string; }, T), { third: string; })'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(36,11): error TS90010: Type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; secondsecond: string; })' is not assignable to type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; secondsecond: string; })'. Two different types with this name exist, but they are unrelated. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(38,11): error TS2322: Type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; secondsecond: string; })' is not assignable to type 'spread(spread({ first: string; second: string; secondsecond: string; third: string; }, T), U)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(42,11): error TS2322: Type 'spread(spread(spread(spread({ firrrrrrst: string; }, T), { second: string; }), U), { third: string; })' is not assignable to type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; })'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(44,11): error TS2322: Type 'spread(spread(spread(spread({ first: string; }, T), { ssssssssecond: string; }), U), { third: string; })' is not assignable to type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; })'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(46,11): error TS2322: Type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { thirrrrrrrd: string; })' is not assignable to type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; })'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(57,5): error TS2322: Type 'spread(keyof U)' is not assignable to type 'spread(keyof T)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(58,5): error TS2322: Type 'spread(keyof T)' is not assignable to type 'spread(keyof U)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(61,5): error TS2322: Type 'spread(K)' is not assignable to type 'spread(keyof T)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(62,5): error TS2322: Type 'spread(keyof T)' is not assignable to type 'spread(K)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(63,5): error TS2322: Type 'spread(J)' is not assignable to type 'spread(keyof U)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(64,5): error TS2322: Type 'spread(keyof U)' is not assignable to type 'spread(J)'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(70,5): error TS2322: Type 'spread(U[J])' is not assignable to type 'spread(T[K])'. +tests/cases/conformance/types/spread/objectSpreadGeneric.ts(71,5): error TS2322: Type 'spread(T[K])' is not assignable to type 'spread(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 + let o: spread(spread(T, U), V); + let uus: spread(U, U); + let us: spread(U); + const same: spread(spread(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 'spread(U)' is not assignable to type 'U'. + const reversed: spread(spread(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 'spread(spread(T, U), V)' is not assignable to type 'spread(spread(V, U), T)'. + const reversed2: spread(spread(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 'spread(spread(T, U), V)' is not assignable to type 'spread(spread(U, T), V)'. + const missingT: spread(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 'spread(spread(T, U), V)' is not assignable to type 'spread(U, V)'. + const missingU: spread(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 'spread(spread(T, U), V)' is not assignable to type 'spread(T, V)'. + const missingV: spread(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 'spread(spread(T, U), V)' is not assignable to type 'spread(T, U)'. + const atEnd: spread(spread(T, U), { second: string }) = { ...t, ...u, second: 'foo' }; // ok + const atBeginning: spread(spread({ first: string }, T), U) = { first: 'foo', ...t, ...u }; // error, not assignable ~~~~~~~~~~~ -!!! error TS90010: Type '{ first: string; ...T; ...U }' is not assignable to type '{ first: string; ...T; ...U }'. Two different types with this name exist, but they are unrelated. +!!! error TS90010: Type 'spread(spread({ first: string; }, T), U)' is not assignable to type 'spread(spread({ first: string; }, T), U)'. Two different types with this name exist, but they are unrelated. const emptyTarget: { } = { ...t, ...u } // ok - const emptySource: { ...T, ...U } = { }; // error, {} is not assignable to U (or T) + const emptySource: spread(T, U) = { }; // error, {} is not assignable to U (or T) ~~~~~~~~~~~ -!!! error TS2322: Type '{}' is not assignable to type '{ ...T; ...U }'. +!!! error TS2322: Type '{}' is not assignable to type 'spread(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 } = + const unionCutoff: spread(T, { sn?: number | string | boolean }) = ~~~~~~~~~~~ -!!! error TS2322: Type '{ sn?: boolean; ...T; sn?: string | number; }' is not assignable to type '{ ...T; sn?: string | number | boolean; }'. +!!! error TS2322: Type 'spread(spread({ sn?: boolean; }, T), { sn?: string | number; })' is not assignable to type 'spread(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 } = + const interspersed: spread(spread(spread(spread({ first: string }, T), { second: string }), U), { third: string }) = ~~~~~~~~~~~~ -!!! error TS90010: Type '{ first: string; ...T; second: string; ...U; third: string; }' is not assignable to type '{ first: string; ...T; second: string; ...U; third: string; }'. Two different types with this name exist, but they are unrelated. +!!! error TS90010: Type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; })' is not assignable to type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; })'. Two different types with this name exist, but they are unrelated. { 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; }'. + const interspersedMissingU: spread(spread({ first: string, second: string }, T), { third: string }) = + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; })' is not assignable to type 'spread(spread({ 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 TS90010: 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; }'. Two different types with this name exist, but they are unrelated. + const interspersedOrder1: spread(spread(spread(spread({ first: string }, T), { second: string }), U), { third: string , secondsecond: string }) = + ~~~~~~~~~~~~~~~~~~ +!!! error TS90010: Type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; secondsecond: string; })' is not assignable to type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; secondsecond: string; })'. Two different types with this name exist, but they are unrelated. { 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 }'. + const interspersedOrder2: spread(spread({ first: string, second: string, secondsecond: string, third: string }, T), U) = + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { third: string; secondsecond: string; })' is not assignable to type 'spread(spread({ 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 } = + const mismatchFirst: spread(spread(spread(spread({ 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; }'. +!!! error TS2322: Type 'spread(spread(spread(spread({ firrrrrrst: string; }, T), { second: string; }), U), { third: string; })' is not assignable to type 'spread(spread(spread(spread({ 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; }'. + const mismatchSecond: spread(spread(spread(spread({ first: string }, T), { second: string }), U), { third: string }) = + ~~~~~~~~~~~~~~ +!!! error TS2322: Type 'spread(spread(spread(spread({ first: string; }, T), { ssssssssecond: string; }), U), { third: string; })' is not assignable to type 'spread(spread(spread(spread({ 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; }'. + const mismatchLast: spread(spread(spread(spread({ first: string }, T), { second: string }), U), { third: string }) = + ~~~~~~~~~~~~ +!!! error TS2322: Type 'spread(spread(spread(spread({ first: string; }, T), { second: string; }), U), { thirrrrrrrd: string; })' is not assignable to type 'spread(spread(spread(spread({ 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 }; + let k1: spread(keyof T); + let k2: spread(keyof U); + let k3: spread(K); + let k4: spread(J); k1 = k1; // ok k2 = k2; // ok k1 = k2; // error ~~ -!!! error TS2322: Type '{ ...keyof U }' is not assignable to type '{ ...keyof T }'. +!!! error TS2322: Type 'spread(keyof U)' is not assignable to type 'spread(keyof T)'. k2 = k1; // error ~~ -!!! error TS2322: Type '{ ...keyof T }' is not assignable to type '{ ...keyof U }'. +!!! error TS2322: Type 'spread(keyof T)' is not assignable to type 'spread(keyof U)'. k3 = k3; // ok k4 = k4; // ok k1 = k3; // error ~~ -!!! error TS2322: Type '{ ...K }' is not assignable to type '{ ...keyof T }'. +!!! error TS2322: Type 'spread(K)' is not assignable to type 'spread(keyof T)'. k3 = k1; // error ~~ -!!! error TS2322: Type '{ ...keyof T }' is not assignable to type '{ ...K }'. +!!! error TS2322: Type 'spread(keyof T)' is not assignable to type 'spread(K)'. k2 = k4; // error ~~ -!!! error TS2322: Type '{ ...J }' is not assignable to type '{ ...keyof U }'. +!!! error TS2322: Type 'spread(J)' is not assignable to type 'spread(keyof U)'. k4 = k2; // error ~~ -!!! error TS2322: Type '{ ...keyof U }' is not assignable to type '{ ...J }'. +!!! error TS2322: Type 'spread(keyof U)' is not assignable to type 'spread(J)'. - let i1: { ...T[K] }; - let i2: { ...U[J] }; + let i1: spread(T[K]); + let i2: spread(U[J]); i1 = i1; // ok i2 = i2; // ok i1 = i2; // error ~~ -!!! error TS2322: Type '{ ...U[J] }' is not assignable to type '{ ...T[K] }'. +!!! error TS2322: Type 'spread(U[J])' is not assignable to type 'spread(T[K])'. i2 = i1; // error ~~ -!!! error TS2322: Type '{ ...T[K] }' is not assignable to type '{ ...U[J] }'. +!!! error TS2322: Type 'spread(T[K])' is not assignable to type 'spread(U[J])'. } \ No newline at end of file diff --git a/tests/baselines/reference/objectSpreadGeneric.js b/tests/baselines/reference/objectSpreadGeneric.js index 9f9c45d9467a9..0681486e99a11 100644 --- a/tests/baselines/reference/objectSpreadGeneric.js +++ b/tests/baselines/reference/objectSpreadGeneric.js @@ -1,58 +1,58 @@ //// [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 + let o: spread(spread(T, U), V); + let uus: spread(U, U); + let us: spread(U); + const same: spread(spread(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 reversed: spread(spread(V, U), T) = o; // error, reversed + const reversed2: spread(spread(U, T), V) = o; // error, U and T are still reversed + const missingT: spread(U, V) = o; // error, missing T + const missingU: spread(T, V) = o; // error, missing U + const missingV: spread(T, U) = o; // error, missing V + const atEnd: spread(spread(T, U), { second: string }) = { ...t, ...u, second: 'foo' }; // ok + const atBeginning: spread(spread({ 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) + const emptySource: spread(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 } = + const unionCutoff: spread(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 } = + const interspersed: spread(spread(spread(spread({ 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 } = + const interspersedMissingU: spread(spread({ 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 } = + const interspersedOrder1: spread(spread(spread(spread({ 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 } = + const interspersedOrder2: spread(spread({ 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 } = + const mismatchFirst: spread(spread(spread(spread({ 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 } = + const mismatchSecond: spread(spread(spread(spread({ 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 } = + const mismatchLast: spread(spread(spread(spread({ 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 }; + let k1: spread(keyof T); + let k2: spread(keyof U); + let k3: spread(K); + let k4: spread(J); k1 = k1; // ok k2 = k2; // ok k1 = k2; // error @@ -64,8 +64,8 @@ function indexAccessedTest(t: T, u: k2 = k4; // error k4 = k2; // error - let i1: { ...T[K] }; - let i2: { ...U[J] }; + let i1: spread(T[K]); + let i2: spread(U[J]); i1 = i1; // ok i2 = i2; // ok i1 = i2; // error diff --git a/tests/baselines/reference/objectSpreadIndexSignature.errors.txt b/tests/baselines/reference/objectSpreadIndexSignature.errors.txt deleted file mode 100644 index 0e1d0dc724224..0000000000000 --- a/tests/baselines/reference/objectSpreadIndexSignature.errors.txt +++ /dev/null @@ -1,38 +0,0 @@ -tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts(6,39): error TS2699: Type literals with spreads cannot contain index, call or constructor signatures. -tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts(27,20): error TS2699: Type literals with spreads cannot contain index, call or constructor 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 constructor signatures. - let n: number = c.a; - let s: string = c[12]; - interface Indexed { - [n: string]: number; - a: number; - } - interface Indexed2 { - [n: string]: boolean; - c: boolean; - } - let indexed: Indexed; - let indexed2: Indexed2; - let i: { ...Indexed, b: number }; - // only indexed has indexer, so i[101]: any - i[101]; - let ii: { ...Indexed, ...Indexed2, b: boolean, d: number }; - // both have indexer, so i[1001]: number | boolean - 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 constructor signatures. - } - \ No newline at end of file diff --git a/tests/baselines/reference/objectSpreadIndexSignature.js b/tests/baselines/reference/objectSpreadIndexSignature.js index f45ab643d4f9e..8975016479a5b 100644 --- a/tests/baselines/reference/objectSpreadIndexSignature.js +++ b/tests/baselines/reference/objectSpreadIndexSignature.js @@ -4,7 +4,7 @@ class C { c: boolean; } // index signatures are not allowed in object literals with spread types -let c: { ...C, b: string, c?: string, [n: number]: string }; +let c: spread(C, { b: string, c?: string, [n: number]: string }); let n: number = c.a; let s: string = c[12]; interface Indexed { @@ -17,15 +17,15 @@ interface Indexed2 { } let indexed: Indexed; let indexed2: Indexed2; -let i: { ...Indexed, b: number }; +let i: spread(Indexed, { b: number }); // only indexed has indexer, so i[101]: any i[101]; -let ii: { ...Indexed, ...Indexed2, b: boolean, d: number }; +let ii: spread(spread(Indexed, Indexed2), { b: boolean, d: number }); // both have indexer, so i[1001]: number | boolean let nb: number | boolean = ii[1001]; function f(t: T) { - let i: { ...T, [n: number]: string }; + let i: spread(T, { [n: number]: string }); } diff --git a/tests/baselines/reference/objectSpreadIndexSignature.symbols b/tests/baselines/reference/objectSpreadIndexSignature.symbols new file mode 100644 index 0000000000000..4c3c4479ad271 --- /dev/null +++ b/tests/baselines/reference/objectSpreadIndexSignature.symbols @@ -0,0 +1,87 @@ +=== tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts === +class C { +>C : Symbol(C, Decl(objectSpreadIndexSignature.ts, 0, 0)) + + a: number; +>a : Symbol(C.a, Decl(objectSpreadIndexSignature.ts, 0, 9)) + + c: boolean; +>c : Symbol(C.c, Decl(objectSpreadIndexSignature.ts, 1, 14)) +} +// index signatures are not allowed in object literals with spread types +let c: spread(C, { b: string, c?: string, [n: number]: string }); +>c : Symbol(c, Decl(objectSpreadIndexSignature.ts, 5, 3)) +>C : Symbol(C, Decl(objectSpreadIndexSignature.ts, 0, 0)) +>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 5, 18)) +>c : Symbol(c, Decl(objectSpreadIndexSignature.ts, 5, 29)) +>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 5, 43)) + +let n: number = c.a; +>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 6, 3)) +>c.a : Symbol(C.a, Decl(objectSpreadIndexSignature.ts, 0, 9)) +>c : Symbol(c, Decl(objectSpreadIndexSignature.ts, 5, 3)) +>a : Symbol(C.a, Decl(objectSpreadIndexSignature.ts, 0, 9)) + +let s: string = c[12]; +>s : Symbol(s, Decl(objectSpreadIndexSignature.ts, 7, 3)) +>c : Symbol(c, Decl(objectSpreadIndexSignature.ts, 5, 3)) + +interface Indexed { +>Indexed : Symbol(Indexed, Decl(objectSpreadIndexSignature.ts, 7, 22)) + + [n: string]: number; +>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 9, 5)) + + a: number; +>a : Symbol(Indexed.a, Decl(objectSpreadIndexSignature.ts, 9, 24)) +} +interface Indexed2 { +>Indexed2 : Symbol(Indexed2, Decl(objectSpreadIndexSignature.ts, 11, 1)) + + [n: string]: boolean; +>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 13, 5)) + + c: boolean; +>c : Symbol(Indexed2.c, Decl(objectSpreadIndexSignature.ts, 13, 25)) +} +let indexed: Indexed; +>indexed : Symbol(indexed, Decl(objectSpreadIndexSignature.ts, 16, 3)) +>Indexed : Symbol(Indexed, Decl(objectSpreadIndexSignature.ts, 7, 22)) + +let indexed2: Indexed2; +>indexed2 : Symbol(indexed2, Decl(objectSpreadIndexSignature.ts, 17, 3)) +>Indexed2 : Symbol(Indexed2, Decl(objectSpreadIndexSignature.ts, 11, 1)) + +let i: spread(Indexed, { b: number }); +>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 18, 3)) +>Indexed : Symbol(Indexed, Decl(objectSpreadIndexSignature.ts, 7, 22)) +>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 18, 24)) + +// only indexed has indexer, so i[101]: any +i[101]; +>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 18, 3)) + +let ii: spread(spread(Indexed, Indexed2), { b: boolean, d: number }); +>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 21, 3)) +>Indexed : Symbol(Indexed, Decl(objectSpreadIndexSignature.ts, 7, 22)) +>Indexed2 : Symbol(Indexed2, Decl(objectSpreadIndexSignature.ts, 11, 1)) +>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 21, 43)) +>d : Symbol(d, Decl(objectSpreadIndexSignature.ts, 21, 55)) + +// both have indexer, so i[1001]: number | boolean +let nb: number | boolean = ii[1001]; +>nb : Symbol(nb, Decl(objectSpreadIndexSignature.ts, 23, 3)) +>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 21, 3)) + +function f(t: T) { +>f : Symbol(f, Decl(objectSpreadIndexSignature.ts, 23, 36)) +>T : Symbol(T, Decl(objectSpreadIndexSignature.ts, 25, 11)) +>t : Symbol(t, Decl(objectSpreadIndexSignature.ts, 25, 14)) +>T : Symbol(T, Decl(objectSpreadIndexSignature.ts, 25, 11)) + + let i: spread(T, { [n: number]: string }); +>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 26, 7)) +>T : Symbol(T, Decl(objectSpreadIndexSignature.ts, 25, 11)) +>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 26, 24)) +} + diff --git a/tests/baselines/reference/objectSpreadIndexSignature.types b/tests/baselines/reference/objectSpreadIndexSignature.types new file mode 100644 index 0000000000000..2900595e28d8f --- /dev/null +++ b/tests/baselines/reference/objectSpreadIndexSignature.types @@ -0,0 +1,93 @@ +=== tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts === +class C { +>C : C + + a: number; +>a : number + + c: boolean; +>c : boolean +} +// index signatures are not allowed in object literals with spread types +let c: spread(C, { b: string, c?: string, [n: number]: string }); +>c : { b: string; c: string | boolean; a: number; } +>C : C +>b : string +>c : string +>n : number + +let n: number = c.a; +>n : number +>c.a : number +>c : { b: string; c: string | boolean; a: number; } +>a : number + +let s: string = c[12]; +>s : string +>c[12] : any +>c : { b: string; c: string | boolean; a: number; } +>12 : 12 + +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: spread(Indexed, { b: number }); +>i : { b: number; a: number; } +>Indexed : Indexed +>b : number + +// only indexed has indexer, so i[101]: any +i[101]; +>i[101] : any +>i : { b: number; a: number; } +>101 : 101 + +let ii: spread(spread(Indexed, Indexed2), { b: boolean, d: number }); +>ii : { b: boolean; d: number; c: boolean; a: number; } +>Indexed : Indexed +>Indexed2 : Indexed2 +>b : boolean +>d : number + +// both have indexer, so i[1001]: number | boolean +let nb: number | boolean = ii[1001]; +>nb : number | boolean +>ii[1001] : any +>ii : { b: boolean; d: number; c: boolean; a: number; } +>1001 : 1001 + +function f(t: T) { +>f : (t: T) => void +>T : T +>t : T +>T : T + + let i: spread(T, { [n: number]: string }); +>i : spread(T, { [n: number]: string; }) +>T : T +>n : number +} + diff --git a/tests/baselines/reference/objectSpreadInference.js b/tests/baselines/reference/objectSpreadInference.js index 77930e565118e..31510fbecf5a2 100644 --- a/tests/baselines/reference/objectSpreadInference.js +++ b/tests/baselines/reference/objectSpreadInference.js @@ -4,8 +4,8 @@ interface Result { 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 }; +declare function infer(tuv: spread(spread(T, U), { a: V })): { t: T, u: U, v: V }; +declare function infer2(utv: spread(spread(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" }); diff --git a/tests/baselines/reference/objectSpreadInference.symbols b/tests/baselines/reference/objectSpreadInference.symbols index cc1b162474684..4d3c17c908d61 100644 --- a/tests/baselines/reference/objectSpreadInference.symbols +++ b/tests/baselines/reference/objectSpreadInference.symbols @@ -17,7 +17,7 @@ interface Result { >v : Symbol(Result.v, Decl(objectSpreadInference.ts, 2, 9)) >V : Symbol(V, Decl(objectSpreadInference.ts, 0, 21)) } -declare function infer(tuv: { ...T, ...U, a: V }): { t: T, u: U, v: V }; +declare function infer(tuv: spread(spread(T, U), { a: V })): { t: T, u: U, v: V }; >infer : Symbol(infer, Decl(objectSpreadInference.ts, 4, 1)) >T : Symbol(T, Decl(objectSpreadInference.ts, 5, 23)) >U : Symbol(U, Decl(objectSpreadInference.ts, 5, 25)) @@ -25,34 +25,34 @@ declare function infer(tuv: { ...T, ...U, a: V }): { t: T, u: U, v: V }; >tuv : Symbol(tuv, Decl(objectSpreadInference.ts, 5, 30)) >T : Symbol(T, Decl(objectSpreadInference.ts, 5, 23)) >U : Symbol(U, Decl(objectSpreadInference.ts, 5, 25)) ->a : Symbol(a, Decl(objectSpreadInference.ts, 5, 48)) +>a : Symbol(a, Decl(objectSpreadInference.ts, 5, 57)) >V : Symbol(V, Decl(objectSpreadInference.ts, 5, 27)) ->t : Symbol(t, Decl(objectSpreadInference.ts, 5, 59)) +>t : Symbol(t, Decl(objectSpreadInference.ts, 5, 69)) >T : Symbol(T, Decl(objectSpreadInference.ts, 5, 23)) ->u : Symbol(u, Decl(objectSpreadInference.ts, 5, 65)) +>u : Symbol(u, Decl(objectSpreadInference.ts, 5, 75)) >U : Symbol(U, Decl(objectSpreadInference.ts, 5, 25)) ->v : Symbol(v, Decl(objectSpreadInference.ts, 5, 71)) +>v : Symbol(v, Decl(objectSpreadInference.ts, 5, 81)) >V : Symbol(V, Decl(objectSpreadInference.ts, 5, 27)) -declare function infer2(utv: { ...U, a: V, ...T }): { t: T, u: U, v: V }; ->infer2 : Symbol(infer2, Decl(objectSpreadInference.ts, 5, 79)) +declare function infer2(utv: spread(spread(U, { a: V }), T )): { t: T, u: U, v: V }; +>infer2 : Symbol(infer2, Decl(objectSpreadInference.ts, 5, 89)) >T : Symbol(T, Decl(objectSpreadInference.ts, 6, 24)) >U : Symbol(U, Decl(objectSpreadInference.ts, 6, 26)) >V : Symbol(V, Decl(objectSpreadInference.ts, 6, 28)) >utv : Symbol(utv, Decl(objectSpreadInference.ts, 6, 31)) >U : Symbol(U, Decl(objectSpreadInference.ts, 6, 26)) ->a : Symbol(a, Decl(objectSpreadInference.ts, 6, 43)) +>a : Symbol(a, Decl(objectSpreadInference.ts, 6, 54)) >V : Symbol(V, Decl(objectSpreadInference.ts, 6, 28)) >T : Symbol(T, Decl(objectSpreadInference.ts, 6, 24)) ->t : Symbol(t, Decl(objectSpreadInference.ts, 6, 60)) +>t : Symbol(t, Decl(objectSpreadInference.ts, 6, 71)) >T : Symbol(T, Decl(objectSpreadInference.ts, 6, 24)) ->u : Symbol(u, Decl(objectSpreadInference.ts, 6, 66)) +>u : Symbol(u, Decl(objectSpreadInference.ts, 6, 77)) >U : Symbol(U, Decl(objectSpreadInference.ts, 6, 26)) ->v : Symbol(v, Decl(objectSpreadInference.ts, 6, 72)) +>v : Symbol(v, Decl(objectSpreadInference.ts, 6, 83)) >V : Symbol(V, Decl(objectSpreadInference.ts, 6, 28)) function generic(w: W, x: X, y: Y) { ->generic : Symbol(generic, Decl(objectSpreadInference.ts, 6, 80)) +>generic : Symbol(generic, Decl(objectSpreadInference.ts, 6, 91)) >W : Symbol(W, Decl(objectSpreadInference.ts, 7, 17)) >X : Symbol(X, Decl(objectSpreadInference.ts, 7, 19)) >Y : Symbol(Y, Decl(objectSpreadInference.ts, 7, 22)) @@ -91,7 +91,7 @@ let i1 = infer({ ...b, ...c, a: 12 }); // can only infer { t: {}, u: {}, v: {} } let i2 = infer2({ ...b, ...c, a: 12 }); >i2 : Symbol(i2, Decl(objectSpreadInference.ts, 16, 3)) ->infer2 : Symbol(infer2, Decl(objectSpreadInference.ts, 5, 79)) +>infer2 : Symbol(infer2, Decl(objectSpreadInference.ts, 5, 89)) >b : Symbol(b, Decl(objectSpreadInference.ts, 11, 3)) >c : Symbol(c, Decl(objectSpreadInference.ts, 12, 3)) >a : Symbol(a, Decl(objectSpreadInference.ts, 16, 29)) @@ -99,7 +99,7 @@ let i2 = infer2({ ...b, ...c, a: 12 }); // can only infer { t: {}, u: {}, v: {} } let i3 = generic(b, c, { a: 12 }); >i3 : Symbol(i3, Decl(objectSpreadInference.ts, 18, 3)) ->generic : Symbol(generic, Decl(objectSpreadInference.ts, 6, 80)) +>generic : Symbol(generic, Decl(objectSpreadInference.ts, 6, 91)) >b : Symbol(b, Decl(objectSpreadInference.ts, 11, 3)) >c : Symbol(c, Decl(objectSpreadInference.ts, 12, 3)) >a : Symbol(a, Decl(objectSpreadInference.ts, 18, 24)) diff --git a/tests/baselines/reference/objectSpreadInference.types b/tests/baselines/reference/objectSpreadInference.types index 0450ad06fc0d7..f03a762dc5cdb 100644 --- a/tests/baselines/reference/objectSpreadInference.types +++ b/tests/baselines/reference/objectSpreadInference.types @@ -17,12 +17,12 @@ interface Result { >v : V >V : V } -declare function infer(tuv: { ...T, ...U, a: V }): { t: T, u: U, v: V }; ->infer : (tuv: { ...T; ...U; a: V; }) => { t: T; u: U; v: V; } +declare function infer(tuv: spread(spread(T, U), { a: V })): { t: T, u: U, v: V }; +>infer : (tuv: spread(spread(T, U), { a: V; })) => { t: T; u: U; v: V; } >T : T >U : U >V : V ->tuv : { ...T; ...U; a: V; } +>tuv : spread(spread(T, U), { a: V; }) >T : T >U : U >a : V @@ -34,12 +34,12 @@ declare function infer(tuv: { ...T, ...U, a: V }): { t: T, u: U, v: V }; >v : V >V : V -declare function infer2(utv: { ...U, a: V, ...T }): { t: T, u: U, v: V }; ->infer2 : (utv: { ...U; a: V; ...T }) => { t: T; u: U; v: V; } +declare function infer2(utv: spread(spread(U, { a: V }), T )): { t: T, u: U, v: V }; +>infer2 : (utv: spread(spread(U, { a: V; }), T)) => { t: T; u: U; v: V; } >T : T >U : U >V : V ->utv : { ...U; a: V; ...T } +>utv : spread(spread(U, { a: V; }), T) >U : U >a : V >V : V @@ -66,8 +66,8 @@ 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" }); >infer({ ...w, ...x, a: y, b: "different type" }) : { t: {}; u: {}; v: {}; } ->infer : (tuv: { ...T; ...U; a: V; }) => { t: T; u: U; v: V; } ->{ ...w, ...x, a: y, b: "different type" } : { ...W; ...X; a: Y; b: string; } +>infer : (tuv: spread(spread(T, U), { a: V; })) => { t: T; u: U; v: V; } +>{ ...w, ...x, a: y, b: "different type" } : spread(spread(W, X), { a: Y; b: string; }) >w : W >x : X >a : Y @@ -87,7 +87,7 @@ let c: { c: number }; let i1 = infer({ ...b, ...c, a: 12 }); >i1 : { t: {}; u: {}; v: {}; } >infer({ ...b, ...c, a: 12 }) : { t: {}; u: {}; v: {}; } ->infer : (tuv: { ...T; ...U; a: V; }) => { t: T; u: U; v: V; } +>infer : (tuv: spread(spread(T, U), { a: V; })) => { t: T; u: U; v: V; } >{ ...b, ...c, a: 12 } : { a: number; c: number; b: number; } >b : { b: number; } >c : { c: number; } @@ -98,7 +98,7 @@ let i1 = infer({ ...b, ...c, a: 12 }); let i2 = infer2({ ...b, ...c, a: 12 }); >i2 : { t: {}; u: {}; v: {}; } >infer2({ ...b, ...c, a: 12 }) : { t: {}; u: {}; v: {}; } ->infer2 : (utv: { ...U; a: V; ...T }) => { t: T; u: U; v: V; } +>infer2 : (utv: spread(spread(U, { a: V; }), T)) => { t: T; u: U; v: V; } >{ ...b, ...c, a: 12 } : { a: number; c: number; b: number; } >b : { b: number; } >c : { c: number; } diff --git a/tests/baselines/reference/objectSpreadIntersection.js b/tests/baselines/reference/objectSpreadIntersection.js index 8f337836ac55c..eb2a51bae8811 100644 --- a/tests/baselines/reference/objectSpreadIntersection.js +++ b/tests/baselines/reference/objectSpreadIntersection.js @@ -3,7 +3,7 @@ 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; + let assignable: spread(spread(T | U, U & V), { id: string }) = result; } // concrete types work interface A1 { a: number } @@ -15,24 +15,24 @@ let b12: B1 & B2; let result = { ...a12, ...b12 }; let sn: number & string = result.a; sn = result.b; -let assignable: { ...(A1 & A2), ...(B1 & B2) } = result; +let assignable: spread(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; + let assignable: spread(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; + let assignable: spread(spread(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; + let assignable: spread(spread(T & U, U | V), { id: string }) = result; } diff --git a/tests/baselines/reference/objectSpreadIntersection.symbols b/tests/baselines/reference/objectSpreadIntersection.symbols index b2ef5add21328..12193da207a98 100644 --- a/tests/baselines/reference/objectSpreadIntersection.symbols +++ b/tests/baselines/reference/objectSpreadIntersection.symbols @@ -27,13 +27,13 @@ function iteratedUnionIntersection(t: T, u: U, v: V): void { >uv : Symbol(uv, Decl(objectSpreadIntersection.ts, 2, 7)) >id : Symbol(id, Decl(objectSpreadIntersection.ts, 3, 32)) - let assignable: { ...(T | U), ...(U & V), id: string } = result; + let assignable: spread(spread(T | U, U & V), { id: string }) = result; >assignable : Symbol(assignable, Decl(objectSpreadIntersection.ts, 4, 7)) >T : Symbol(T, Decl(objectSpreadIntersection.ts, 0, 35)) >U : Symbol(U, Decl(objectSpreadIntersection.ts, 0, 37)) >U : Symbol(U, Decl(objectSpreadIntersection.ts, 0, 37)) >V : Symbol(V, Decl(objectSpreadIntersection.ts, 0, 40)) ->id : Symbol(id, Decl(objectSpreadIntersection.ts, 4, 45)) +>id : Symbol(id, Decl(objectSpreadIntersection.ts, 4, 50)) >result : Symbol(result, Decl(objectSpreadIntersection.ts, 3, 7)) } // concrete types work @@ -80,7 +80,7 @@ sn = result.b; >result : Symbol(result, Decl(objectSpreadIntersection.ts, 13, 3)) >b : Symbol(b, Decl(objectSpreadIntersection.ts, 9, 14), Decl(objectSpreadIntersection.ts, 10, 14)) -let assignable: { ...(A1 & A2), ...(B1 & B2) } = result; +let assignable: spread(A1 & A2, B1 & B2) = result; >assignable : Symbol(assignable, Decl(objectSpreadIntersection.ts, 16, 3)) >A1 : Symbol(A1, Decl(objectSpreadIntersection.ts, 5, 1)) >A2 : Symbol(A2, Decl(objectSpreadIntersection.ts, 7, 26)) @@ -89,7 +89,7 @@ let assignable: { ...(A1 & A2), ...(B1 & B2) } = result; >result : Symbol(result, Decl(objectSpreadIntersection.ts, 13, 3)) function tripleIntersection(t: T, u: U, v: V): void { ->tripleIntersection : Symbol(tripleIntersection, Decl(objectSpreadIntersection.ts, 16, 56)) +>tripleIntersection : Symbol(tripleIntersection, Decl(objectSpreadIntersection.ts, 16, 50)) >T : Symbol(T, Decl(objectSpreadIntersection.ts, 18, 28)) >U : Symbol(U, Decl(objectSpreadIntersection.ts, 18, 30)) >V : Symbol(V, Decl(objectSpreadIntersection.ts, 18, 33)) @@ -111,12 +111,12 @@ function tripleIntersection(t: T, u: U, v: V): void { >tuv : Symbol(tuv, Decl(objectSpreadIntersection.ts, 19, 7)) >id : Symbol(id, Decl(objectSpreadIntersection.ts, 20, 26)) - let assignable: { ...(T & U & V), id: string } = result; + let assignable: spread(T & U & V, { id: string }) = result; >assignable : Symbol(assignable, Decl(objectSpreadIntersection.ts, 21, 7)) >T : Symbol(T, Decl(objectSpreadIntersection.ts, 18, 28)) >U : Symbol(U, Decl(objectSpreadIntersection.ts, 18, 30)) >V : Symbol(V, Decl(objectSpreadIntersection.ts, 18, 33)) ->id : Symbol(id, Decl(objectSpreadIntersection.ts, 21, 37)) +>id : Symbol(id, Decl(objectSpreadIntersection.ts, 21, 39)) >result : Symbol(result, Decl(objectSpreadIntersection.ts, 20, 7)) } function iteratedDoubleIntersection(t: T, u: U, v: V): void { @@ -147,13 +147,13 @@ function iteratedDoubleIntersection(t: T, u: U, v: V): void { >uv : Symbol(uv, Decl(objectSpreadIntersection.ts, 25, 7)) >id : Symbol(id, Decl(objectSpreadIntersection.ts, 26, 32)) - let assignable: { ...(T & U), ...(U & V), id: string } = result; + let assignable: spread(spread(T & U, U & V), { id: string }) = result; >assignable : Symbol(assignable, Decl(objectSpreadIntersection.ts, 27, 7)) >T : Symbol(T, Decl(objectSpreadIntersection.ts, 23, 36)) >U : Symbol(U, Decl(objectSpreadIntersection.ts, 23, 38)) >U : Symbol(U, Decl(objectSpreadIntersection.ts, 23, 38)) >V : Symbol(V, Decl(objectSpreadIntersection.ts, 23, 41)) ->id : Symbol(id, Decl(objectSpreadIntersection.ts, 27, 45)) +>id : Symbol(id, Decl(objectSpreadIntersection.ts, 27, 50)) >result : Symbol(result, Decl(objectSpreadIntersection.ts, 26, 7)) } function iteratedIntersectionUnion(t: T, u: U, v: V): void { @@ -184,13 +184,13 @@ function iteratedIntersectionUnion(t: T, u: U, v: V): void { >uv : Symbol(uv, Decl(objectSpreadIntersection.ts, 31, 7)) >id : Symbol(id, Decl(objectSpreadIntersection.ts, 32, 32)) - let assignable: { ...(T & U), ...(U | V), id: string } = result; + let assignable: spread(spread(T & U, U | V), { id: string }) = result; >assignable : Symbol(assignable, Decl(objectSpreadIntersection.ts, 33, 7)) >T : Symbol(T, Decl(objectSpreadIntersection.ts, 29, 35)) >U : Symbol(U, Decl(objectSpreadIntersection.ts, 29, 37)) >U : Symbol(U, Decl(objectSpreadIntersection.ts, 29, 37)) >V : Symbol(V, Decl(objectSpreadIntersection.ts, 29, 40)) ->id : Symbol(id, Decl(objectSpreadIntersection.ts, 33, 45)) +>id : Symbol(id, Decl(objectSpreadIntersection.ts, 33, 50)) >result : Symbol(result, Decl(objectSpreadIntersection.ts, 32, 7)) } diff --git a/tests/baselines/reference/objectSpreadIntersection.types b/tests/baselines/reference/objectSpreadIntersection.types index fe1259e37a762..9ba434482ea0a 100644 --- a/tests/baselines/reference/objectSpreadIntersection.types +++ b/tests/baselines/reference/objectSpreadIntersection.types @@ -22,21 +22,21 @@ function iteratedUnionIntersection(t: T, u: U, v: V): void { >V : V let result = { ...tu, ...uv, id: 'foo' }; ->result : { ...T; ...U & V; id: string; } | { ...U; ...U & V; id: string; } ->{ ...tu, ...uv, id: 'foo' } : { ...T; ...U & V; id: string; } | { ...U; ...U & V; id: string; } +>result : spread(spread(T, U & V), { id: string; }) | spread(spread(U, U & V), { id: string; }) +>{ ...tu, ...uv, id: 'foo' } : spread(spread(T, U & V), { id: string; }) | spread(spread(U, U & V), { id: string; }) >tu : T | U >uv : U & V >id : string >'foo' : "foo" - let assignable: { ...(T | U), ...(U & V), id: string } = result; ->assignable : { ...T; ...U & V; id: string; } | { ...U; ...U & V; id: string; } + let assignable: spread(spread(T | U, U & V), { id: string }) = result; +>assignable : spread(spread(T, U & V), { id: string; }) | spread(spread(U, U & V), { id: string; }) >T : T >U : U >U : U >V : V >id : string ->result : { ...T; ...U & V; id: string; } | { ...U; ...U & V; id: string; } +>result : spread(spread(T, U & V), { id: string; }) | spread(spread(U, U & V), { id: string; }) } // concrete types work interface A1 { a: number } @@ -84,7 +84,7 @@ sn = result.b; >result : { b: number & string; a: number & string; } >b : number & string -let assignable: { ...(A1 & A2), ...(B1 & B2) } = result; +let assignable: spread(A1 & A2, B1 & B2) = result; >assignable : { b: number & string; a: number & string; } >A1 : A1 >A2 : A2 @@ -111,19 +111,19 @@ function tripleIntersection(t: T, u: U, v: V): void { >V : V let result = { ...tuv, id: 'bar' }; ->result : { ...T & U & V; id: string; } ->{ ...tuv, id: 'bar' } : { ...T & U & V; id: string; } +>result : spread(T & U & V, { id: string; }) +>{ ...tuv, id: 'bar' } : spread(T & U & V, { id: string; }) >tuv : T & U & V >id : string >'bar' : "bar" - let assignable: { ...(T & U & V), id: string } = result; ->assignable : { ...T & U & V; id: string; } + let assignable: spread(T & U & V, { id: string }) = result; +>assignable : spread(T & U & V, { id: string; }) >T : T >U : U >V : V >id : string ->result : { ...T & U & V; id: string; } +>result : spread(T & U & V, { id: string; }) } function iteratedDoubleIntersection(t: T, u: U, v: V): void { >iteratedDoubleIntersection : (t: T, u: U, v: V) => void @@ -148,21 +148,21 @@ function iteratedDoubleIntersection(t: T, u: U, v: V): void { >V : V let result = { ...tu, ...uv, id: 'baz' }; ->result : { ...T & U; ...U & V; id: string; } ->{ ...tu, ...uv, id: 'baz' } : { ...T & U; ...U & V; id: string; } +>result : spread(spread(T & U, U & V), { id: string; }) +>{ ...tu, ...uv, id: 'baz' } : spread(spread(T & U, U & V), { id: string; }) >tu : T & U >uv : U & V >id : string >'baz' : "baz" - let assignable: { ...(T & U), ...(U & V), id: string } = result; ->assignable : { ...T & U; ...U & V; id: string; } + let assignable: spread(spread(T & U, U & V), { id: string }) = result; +>assignable : spread(spread(T & U, U & V), { id: string; }) >T : T >U : U >U : U >V : V >id : string ->result : { ...T & U; ...U & V; id: string; } +>result : spread(spread(T & U, U & V), { id: string; }) } function iteratedIntersectionUnion(t: T, u: U, v: V): void { >iteratedIntersectionUnion : (t: T, u: U, v: V) => void @@ -187,20 +187,20 @@ function iteratedIntersectionUnion(t: T, u: U, v: V): void { >V : V let result = { ...tu, ...uv, id: 'qux' }; ->result : { ...T & U; ...U; id: string; } | { ...T & U; ...V; id: string; } ->{ ...tu, ...uv, id: 'qux' } : { ...T & U; ...U; id: string; } | { ...T & U; ...V; id: string; } +>result : spread(spread(T & U, U), { id: string; }) | spread(spread(T & U, V), { id: string; }) +>{ ...tu, ...uv, id: 'qux' } : spread(spread(T & U, U), { id: string; }) | spread(spread(T & U, V), { id: string; }) >tu : T & U >uv : U | V >id : string >'qux' : "qux" - let assignable: { ...(T & U), ...(U | V), id: string } = result; ->assignable : { ...T & U; ...U; id: string; } | { ...T & U; ...V; id: string; } + let assignable: spread(spread(T & U, U | V), { id: string }) = result; +>assignable : spread(spread(T & U, U), { id: string; }) | spread(spread(T & U, V), { id: string; }) >T : T >U : U >U : U >V : V >id : string ->result : { ...T & U; ...U; id: string; } | { ...T & U; ...V; id: string; } +>result : spread(spread(T & U, U), { id: string; }) | spread(spread(T & U, V), { id: string; }) } diff --git a/tests/baselines/reference/objectSpreadNegative.errors.txt b/tests/baselines/reference/objectSpreadNegative.errors.txt index 5d6fd1b4e9d62..1e908a5df2341 100644 --- a/tests/baselines/reference/objectSpreadNegative.errors.txt +++ b/tests/baselines/reference/objectSpreadNegative.errors.txt @@ -16,15 +16,13 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(40,19): error TS269 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 constructor signatures. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(57,69): error TS2699: Type literals with spreads cannot contain index, call or constructor 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(64,9): error TS2322: Type 'spread(T & V)' is not assignable to type 'spread(T & U)'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS2322: Type 'spread(U)' is not assignable to type 'U'. -==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (21 errors) ==== +==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (19 errors) ==== let o = { a: 1, b: 'no' } /// private propagates @@ -34,7 +32,7 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS232 class PublicX { public x: number; } - let o2: { ...PublicX, ...PrivateOptionalX }; + let o2: spread(PublicX, PrivateOptionalX); let sn: number = o2.x; // error, x is private ~ !!! error TS2339: Property 'x' does not exist on type '{}'. @@ -49,7 +47,7 @@ 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: spread(Bool, Str) = { 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; }'. @@ -114,11 +112,7 @@ 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 constructor signatures. - ~~~~~~~~~~~~~~~ -!!! error TS2699: Type literals with spreads cannot contain index, call or constructor signatures. + let callableConstructableSpread: spread(PublicX, { (n: number): number, new (p: number) }); 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. @@ -128,13 +122,13 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(66,12): error TS232 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; + let tvs: spread(T & V); + let mistake: spread(T & U) = tvs; ~~~~~~~ -!!! error TS2322: Type '{ ...T & V }' is not assignable to type '{ ...T & U }'. +!!! error TS2322: Type 'spread(T & V)' is not assignable to type 'spread(T & U)'. // { ...U } is not assignable to U return { ...initial, ...override }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '{ ...U }' is not assignable to type 'U'. +!!! error TS2322: Type 'spread(U)' is not assignable to type 'U'. } \ No newline at end of file diff --git a/tests/baselines/reference/objectSpreadNegative.js b/tests/baselines/reference/objectSpreadNegative.js index e6283271172ca..e2558d52c9f36 100644 --- a/tests/baselines/reference/objectSpreadNegative.js +++ b/tests/baselines/reference/objectSpreadNegative.js @@ -8,7 +8,7 @@ class PrivateOptionalX { class PublicX { public x: number; } -let o2: { ...PublicX, ...PrivateOptionalX }; +let o2: spread(PublicX, PrivateOptionalX); let sn: number = o2.x; // error, x is private let optionalString: { sn?: string }; let optionalNumber: { sn?: number }; @@ -18,7 +18,7 @@ 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 spread: spread(Bool, Str) = { s: "foo" }; // error, missing 'b' let b: Bool; spread = b; // error, missing 's' @@ -55,14 +55,14 @@ 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) }; +let callableConstructableSpread: spread(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; + let tvs: spread(T & V); + let mistake: spread(T & U) = tvs; // { ...U } is not assignable to U return { ...initial, ...override }; } diff --git a/tests/baselines/reference/objectSpreadScenarios.js b/tests/baselines/reference/objectSpreadScenarios.js index 96ac98d2d3593..901499447ad04 100644 --- a/tests/baselines/reference/objectSpreadScenarios.js +++ b/tests/baselines/reference/objectSpreadScenarios.js @@ -1,13 +1,13 @@ //// [objectSpreadScenarios.ts] interface A1 { a: boolean } interface B1 { b: number }; -function override(initial: U, override: U): { ...U, ...U } { +function override(initial: U, override: U): spread(U, U) { return { ...initial, ...override }; } -function update(this: { u: { ...U } }, override: U): void { +function update(this: { u: spread(U) }, override: U): void { this.u = { ...this.u, ...override }; } -function mixin(one: T, two: U): { ...T, ...U } { +function mixin(one: T, two: U): spread(T, U) { return { ...one, ...two }; } let a1: A1 = { a: true }; diff --git a/tests/baselines/reference/objectSpreadScenarios.symbols b/tests/baselines/reference/objectSpreadScenarios.symbols index df27f89922ac6..29b18808a8e4b 100644 --- a/tests/baselines/reference/objectSpreadScenarios.symbols +++ b/tests/baselines/reference/objectSpreadScenarios.symbols @@ -7,7 +7,7 @@ interface B1 { b: number }; >B1 : Symbol(B1, Decl(objectSpreadScenarios.ts, 0, 27)) >b : Symbol(B1.b, Decl(objectSpreadScenarios.ts, 1, 14)) -function override(initial: U, override: U): { ...U, ...U } { +function override(initial: U, override: U): spread(U, U) { >override : Symbol(override, Decl(objectSpreadScenarios.ts, 1, 27)) >U : Symbol(U, Decl(objectSpreadScenarios.ts, 2, 18)) >initial : Symbol(initial, Decl(objectSpreadScenarios.ts, 2, 21)) @@ -21,13 +21,13 @@ function override(initial: U, override: U): { ...U, ...U } { >initial : Symbol(initial, Decl(objectSpreadScenarios.ts, 2, 21)) >override : Symbol(override, Decl(objectSpreadScenarios.ts, 2, 32)) } -function update(this: { u: { ...U } }, override: U): void { +function update(this: { u: spread(U) }, override: U): void { >update : Symbol(update, Decl(objectSpreadScenarios.ts, 4, 1)) >U : Symbol(U, Decl(objectSpreadScenarios.ts, 5, 16)) >this : Symbol(this, Decl(objectSpreadScenarios.ts, 5, 19)) >u : Symbol(u, Decl(objectSpreadScenarios.ts, 5, 26)) >U : Symbol(U, Decl(objectSpreadScenarios.ts, 5, 16)) ->override : Symbol(override, Decl(objectSpreadScenarios.ts, 5, 41)) +>override : Symbol(override, Decl(objectSpreadScenarios.ts, 5, 42)) >U : Symbol(U, Decl(objectSpreadScenarios.ts, 5, 16)) this.u = { ...this.u, ...override }; @@ -37,9 +37,9 @@ function update(this: { u: { ...U } }, override: U): void { >this.u : Symbol(u, Decl(objectSpreadScenarios.ts, 5, 26)) >this : Symbol(this, Decl(objectSpreadScenarios.ts, 5, 19)) >u : Symbol(u, Decl(objectSpreadScenarios.ts, 5, 26)) ->override : Symbol(override, Decl(objectSpreadScenarios.ts, 5, 41)) +>override : Symbol(override, Decl(objectSpreadScenarios.ts, 5, 42)) } -function mixin(one: T, two: U): { ...T, ...U } { +function mixin(one: T, two: U): spread(T, U) { >mixin : Symbol(mixin, Decl(objectSpreadScenarios.ts, 7, 1)) >T : Symbol(T, Decl(objectSpreadScenarios.ts, 8, 15)) >U : Symbol(U, Decl(objectSpreadScenarios.ts, 8, 17)) diff --git a/tests/baselines/reference/objectSpreadScenarios.types b/tests/baselines/reference/objectSpreadScenarios.types index 483a92cdb354e..232a8b96ab063 100644 --- a/tests/baselines/reference/objectSpreadScenarios.types +++ b/tests/baselines/reference/objectSpreadScenarios.types @@ -7,8 +7,8 @@ interface B1 { b: number }; >B1 : B1 >b : number -function override(initial: U, override: U): { ...U, ...U } { ->override : (initial: U, override: U) => { ...U } +function override(initial: U, override: U): spread(U, U) { +>override : (initial: U, override: U) => spread(U) >U : U >initial : U >U : U @@ -18,32 +18,32 @@ function override(initial: U, override: U): { ...U, ...U } { >U : U return { ...initial, ...override }; ->{ ...initial, ...override } : { ...U } +>{ ...initial, ...override } : spread(U) >initial : U >override : U } -function update(this: { u: { ...U } }, override: U): void { ->update : (this: { u: { ...U }; }, override: U) => void +function update(this: { u: spread(U) }, override: U): void { +>update : (this: { u: spread(U); }, override: U) => void >U : U ->this : { u: { ...U }; } ->u : { ...U } +>this : { u: spread(U); } +>u : spread(U) >U : U >override : U >U : U this.u = { ...this.u, ...override }; ->this.u = { ...this.u, ...override } : { ...U } ->this.u : { ...U } ->this : { u: { ...U }; } ->u : { ...U } ->{ ...this.u, ...override } : { ...U } ->this.u : { ...U } ->this : { u: { ...U }; } ->u : { ...U } +>this.u = { ...this.u, ...override } : spread(U) +>this.u : spread(U) +>this : { u: spread(U); } +>u : spread(U) +>{ ...this.u, ...override } : spread(U) +>this.u : spread(U) +>this : { u: spread(U); } +>u : spread(U) >override : U } -function mixin(one: T, two: U): { ...T, ...U } { ->mixin : (one: T, two: U) => { ...T; ...U } +function mixin(one: T, two: U): spread(T, U) { +>mixin : (one: T, two: U) => spread(T, U) >T : T >U : U >one : T @@ -54,7 +54,7 @@ function mixin(one: T, two: U): { ...T, ...U } { >U : U return { ...one, ...two }; ->{ ...one, ...two } : { ...T; ...U } +>{ ...one, ...two } : spread(T, U) >one : T >two : U } @@ -76,24 +76,24 @@ a1 = override(a1, { a: false }); >a1 = override(a1, { a: false }) : { a: boolean; } >a1 : A1 >override(a1, { a: false }) : { a: boolean; } ->override : (initial: U, override: U) => { ...U } +>override : (initial: U, override: U) => spread(U) >a1 : A1 >{ a: false } : { a: false; } >a : boolean >false : false let host = { u: a1, update }; ->host : { u: A1; update: (this: { u: { ...U }; }, override: U) => void; } ->{ u: a1, update } : { u: A1; update: (this: { u: { ...U }; }, override: U) => void; } +>host : { u: A1; update: (this: { u: spread(U); }, override: U) => void; } +>{ u: a1, update } : { u: A1; update: (this: { u: spread(U); }, override: U) => void; } >u : A1 >a1 : A1 ->update : (this: { u: { ...U }; }, override: U) => void +>update : (this: { u: spread(U); }, override: U) => void host.update({ a: false }); >host.update({ a: false }) : void ->host.update : (this: { u: { ...U }; }, override: U) => void ->host : { u: A1; update: (this: { u: { ...U }; }, override: U) => void; } ->update : (this: { u: { ...U }; }, override: U) => void +>host.update : (this: { u: spread(U); }, override: U) => void +>host : { u: A1; update: (this: { u: spread(U); }, override: U) => void; } +>update : (this: { u: spread(U); }, override: U) => void >{ a: false } : { a: false; } >a : boolean >false : false @@ -101,7 +101,7 @@ host.update({ a: false }); let mixed = mixin(a1, b1); >mixed : { b: number; a: boolean; } >mixin(a1, b1) : { b: number; a: boolean; } ->mixin : (one: T, two: U) => { ...T; ...U } +>mixin : (one: T, two: U) => spread(T, U) >a1 : A1 >b1 : B1 diff --git a/tests/baselines/reference/objectSpreadUnion.js b/tests/baselines/reference/objectSpreadUnion.js index 10342e82f9b34..4dcfe8162ca58 100644 --- a/tests/baselines/reference/objectSpreadUnion.js +++ b/tests/baselines/reference/objectSpreadUnion.js @@ -5,20 +5,20 @@ interface A2 { a: string } let a12: A1 | A2; let result = { ...a12 }; let sn: number | string = result.a; -let assignable: { ...(A1 | A2) } = result; +let assignable: spread(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; + let expected: spread(T, { id: string }) | spread(U, { id: string }) | spread(V, { id: string }) = result; + let assignable: spread(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; + let expected: spread(spread(T, U), { id: string }) | spread(spread(T, V), { id: string }) | spread(U, { id: string }) | spread(spread(U, V), { id: string }); + let assignable: spread(spread(T | U, U | V), { id: string }) = result; } diff --git a/tests/baselines/reference/objectSpreadUnion.symbols b/tests/baselines/reference/objectSpreadUnion.symbols index 26c11cd580f27..532e4b8ecb103 100644 --- a/tests/baselines/reference/objectSpreadUnion.symbols +++ b/tests/baselines/reference/objectSpreadUnion.symbols @@ -23,14 +23,14 @@ let sn: number | string = result.a; >result : Symbol(result, Decl(objectSpreadUnion.ts, 4, 3)) >a : Symbol(a, Decl(objectSpreadUnion.ts, 1, 14), Decl(objectSpreadUnion.ts, 2, 14)) -let assignable: { ...(A1 | A2) } = result; +let assignable: spread(A1 | A2) = result; >assignable : Symbol(assignable, Decl(objectSpreadUnion.ts, 6, 3)) >A1 : Symbol(A1, Decl(objectSpreadUnion.ts, 0, 0)) >A2 : Symbol(A2, Decl(objectSpreadUnion.ts, 1, 26)) >result : Symbol(result, Decl(objectSpreadUnion.ts, 4, 3)) function tripleUnion(t: T, u: U, v: V): void { ->tripleUnion : Symbol(tripleUnion, Decl(objectSpreadUnion.ts, 6, 42)) +>tripleUnion : Symbol(tripleUnion, Decl(objectSpreadUnion.ts, 6, 41)) >T : Symbol(T, Decl(objectSpreadUnion.ts, 8, 21)) >U : Symbol(U, Decl(objectSpreadUnion.ts, 8, 23)) >V : Symbol(V, Decl(objectSpreadUnion.ts, 8, 26)) @@ -52,22 +52,22 @@ function tripleUnion(t: T, u: U, v: V): void { >tuv : Symbol(tuv, Decl(objectSpreadUnion.ts, 9, 7)) >id : Symbol(id, Decl(objectSpreadUnion.ts, 10, 26)) - let expected: { ...T, id: string } | { ...U, id: string } | { ...V, id: string } = result; + let expected: spread(T, { id: string }) | spread(U, { id: string }) | spread(V, { id: string }) = result; >expected : Symbol(expected, Decl(objectSpreadUnion.ts, 11, 7)) >T : Symbol(T, Decl(objectSpreadUnion.ts, 8, 21)) ->id : Symbol(id, Decl(objectSpreadUnion.ts, 11, 25)) +>id : Symbol(id, Decl(objectSpreadUnion.ts, 11, 29)) >U : Symbol(U, Decl(objectSpreadUnion.ts, 8, 23)) ->id : Symbol(id, Decl(objectSpreadUnion.ts, 11, 48)) +>id : Symbol(id, Decl(objectSpreadUnion.ts, 11, 57)) >V : Symbol(V, Decl(objectSpreadUnion.ts, 8, 26)) ->id : Symbol(id, Decl(objectSpreadUnion.ts, 11, 71)) +>id : Symbol(id, Decl(objectSpreadUnion.ts, 11, 85)) >result : Symbol(result, Decl(objectSpreadUnion.ts, 10, 7)) - let assignable: { ...(T | U | V), id: string } = result; + let assignable: spread(T | U | V, { id: string }) = result; >assignable : Symbol(assignable, Decl(objectSpreadUnion.ts, 12, 7)) >T : Symbol(T, Decl(objectSpreadUnion.ts, 8, 21)) >U : Symbol(U, Decl(objectSpreadUnion.ts, 8, 23)) >V : Symbol(V, Decl(objectSpreadUnion.ts, 8, 26)) ->id : Symbol(id, Decl(objectSpreadUnion.ts, 12, 37)) +>id : Symbol(id, Decl(objectSpreadUnion.ts, 12, 39)) >result : Symbol(result, Decl(objectSpreadUnion.ts, 10, 7)) } function iteratedDoubleUnion(t: T, u: U, v: V): void { @@ -98,27 +98,27 @@ function iteratedDoubleUnion(t: T, u: U, v: V): void { >uv : Symbol(uv, Decl(objectSpreadUnion.ts, 16, 7)) >id : Symbol(id, Decl(objectSpreadUnion.ts, 17, 32)) - let expected: { ...T, ...U, id: string } | { ...T, ...V, id: string } | { ...U, id: string } | { ...U, ...V, id: string }; + let expected: spread(spread(T, U), { id: string }) | spread(spread(T, V), { id: string }) | spread(U, { id: string }) | spread(spread(U, V), { id: string }); >expected : Symbol(expected, Decl(objectSpreadUnion.ts, 18, 7)) >T : Symbol(T, Decl(objectSpreadUnion.ts, 14, 29)) >U : Symbol(U, Decl(objectSpreadUnion.ts, 14, 31)) ->id : Symbol(id, Decl(objectSpreadUnion.ts, 18, 31)) +>id : Symbol(id, Decl(objectSpreadUnion.ts, 18, 40)) >T : Symbol(T, Decl(objectSpreadUnion.ts, 14, 29)) >V : Symbol(V, Decl(objectSpreadUnion.ts, 14, 34)) ->id : Symbol(id, Decl(objectSpreadUnion.ts, 18, 60)) +>id : Symbol(id, Decl(objectSpreadUnion.ts, 18, 79)) >U : Symbol(U, Decl(objectSpreadUnion.ts, 14, 31)) ->id : Symbol(id, Decl(objectSpreadUnion.ts, 18, 83)) +>id : Symbol(id, Decl(objectSpreadUnion.ts, 18, 107)) >U : Symbol(U, Decl(objectSpreadUnion.ts, 14, 31)) >V : Symbol(V, Decl(objectSpreadUnion.ts, 14, 34)) ->id : Symbol(id, Decl(objectSpreadUnion.ts, 18, 112)) +>id : Symbol(id, Decl(objectSpreadUnion.ts, 18, 146)) - let assignable: { ...(T | U), ...(U | V), id: string } = result; + let assignable: spread(spread(T | U, U | V), { id: string }) = result; >assignable : Symbol(assignable, Decl(objectSpreadUnion.ts, 19, 7)) >T : Symbol(T, Decl(objectSpreadUnion.ts, 14, 29)) >U : Symbol(U, Decl(objectSpreadUnion.ts, 14, 31)) >U : Symbol(U, Decl(objectSpreadUnion.ts, 14, 31)) >V : Symbol(V, Decl(objectSpreadUnion.ts, 14, 34)) ->id : Symbol(id, Decl(objectSpreadUnion.ts, 19, 45)) +>id : Symbol(id, Decl(objectSpreadUnion.ts, 19, 50)) >result : Symbol(result, Decl(objectSpreadUnion.ts, 17, 7)) } diff --git a/tests/baselines/reference/objectSpreadUnion.types b/tests/baselines/reference/objectSpreadUnion.types index 7733aadb0cb49..33d642a2f2f72 100644 --- a/tests/baselines/reference/objectSpreadUnion.types +++ b/tests/baselines/reference/objectSpreadUnion.types @@ -24,7 +24,7 @@ let sn: number | string = result.a; >result : { a: number; } | { a: string; } >a : string | number -let assignable: { ...(A1 | A2) } = result; +let assignable: spread(A1 | A2) = result; >assignable : { a: number; } | { a: string; } >A1 : A1 >A2 : A2 @@ -49,29 +49,29 @@ function tripleUnion(t: T, u: U, v: V): void { >V : V let result = { ...tuv, id: 'foo' }; ->result : { ...T; id: string; } | { ...U; id: string; } | { ...V; id: string; } ->{ ...tuv, id: 'foo' } : { ...T; id: string; } | { ...U; id: string; } | { ...V; id: string; } +>result : spread(T, { id: string; }) | spread(U, { id: string; }) | spread(V, { id: string; }) +>{ ...tuv, id: 'foo' } : spread(T, { id: string; }) | spread(U, { id: string; }) | spread(V, { id: string; }) >tuv : T | U | V >id : string >'foo' : "foo" - let expected: { ...T, id: string } | { ...U, id: string } | { ...V, id: string } = result; ->expected : { ...T; id: string; } | { ...U; id: string; } | { ...V; id: string; } + let expected: spread(T, { id: string }) | spread(U, { id: string }) | spread(V, { id: string }) = result; +>expected : spread(T, { id: string; }) | spread(U, { id: string; }) | spread(V, { id: string; }) >T : T >id : string >U : U >id : string >V : V >id : string ->result : { ...T; id: string; } | { ...U; id: string; } | { ...V; id: string; } +>result : spread(T, { id: string; }) | spread(U, { id: string; }) | spread(V, { id: string; }) - let assignable: { ...(T | U | V), id: string } = result; ->assignable : { ...T; id: string; } | { ...U; id: string; } | { ...V; id: string; } + let assignable: spread(T | U | V, { id: string }) = result; +>assignable : spread(T, { id: string; }) | spread(U, { id: string; }) | spread(V, { id: string; }) >T : T >U : U >V : V >id : string ->result : { ...T; id: string; } | { ...U; id: string; } | { ...V; id: string; } +>result : spread(T, { id: string; }) | spread(U, { id: string; }) | spread(V, { id: string; }) } function iteratedDoubleUnion(t: T, u: U, v: V): void { >iteratedDoubleUnion : (t: T, u: U, v: V) => void @@ -96,15 +96,15 @@ function iteratedDoubleUnion(t: T, u: U, v: V): void { >V : V let result = { ...tu, ...uv, id: 'bar' }; ->result : { ...U; id: string; } | { ...T; ...U; id: string; } | { ...T; ...V; id: string; } | { ...U; ...V; id: string; } ->{ ...tu, ...uv, id: 'bar' } : { ...U; id: string; } | { ...T; ...U; id: string; } | { ...T; ...V; id: string; } | { ...U; ...V; id: string; } +>result : spread(U, { id: string; }) | spread(spread(T, U), { id: string; }) | spread(spread(T, V), { id: string; }) | spread(spread(U, V), { id: string; }) +>{ ...tu, ...uv, id: 'bar' } : spread(U, { id: string; }) | spread(spread(T, U), { id: string; }) | spread(spread(T, V), { id: string; }) | spread(spread(U, V), { id: string; }) >tu : T | U >uv : U | V >id : string >'bar' : "bar" - let expected: { ...T, ...U, id: string } | { ...T, ...V, id: string } | { ...U, id: string } | { ...U, ...V, id: string }; ->expected : { ...T; ...U; id: string; } | { ...T; ...V; id: string; } | { ...U; id: string; } | { ...U; ...V; id: string; } + let expected: spread(spread(T, U), { id: string }) | spread(spread(T, V), { id: string }) | spread(U, { id: string }) | spread(spread(U, V), { id: string }); +>expected : spread(spread(T, U), { id: string; }) | spread(spread(T, V), { id: string; }) | spread(U, { id: string; }) | spread(spread(U, V), { id: string; }) >T : T >U : U >id : string @@ -117,13 +117,13 @@ function iteratedDoubleUnion(t: T, u: U, v: V): void { >V : V >id : string - let assignable: { ...(T | U), ...(U | V), id: string } = result; ->assignable : { ...U; id: string; } | { ...T; ...U; id: string; } | { ...T; ...V; id: string; } | { ...U; ...V; id: string; } + let assignable: spread(spread(T | U, U | V), { id: string }) = result; +>assignable : spread(U, { id: string; }) | spread(spread(T, U), { id: string; }) | spread(spread(T, V), { id: string; }) | spread(spread(U, V), { id: string; }) >T : T >U : U >U : U >V : V >id : string ->result : { ...U; id: string; } | { ...T; ...U; id: string; } | { ...T; ...V; id: string; } | { ...U; ...V; id: string; } +>result : spread(U, { id: string; }) | spread(spread(T, U), { id: string; }) | spread(spread(T, V), { id: string; }) | spread(spread(U, V), { id: string; }) } diff --git a/tests/baselines/reference/spreadLeftDeep.js b/tests/baselines/reference/spreadLeftDeep.js new file mode 100644 index 0000000000000..c146ffac5a214 --- /dev/null +++ b/tests/baselines/reference/spreadLeftDeep.js @@ -0,0 +1,16 @@ +//// [spreadLeftDeep.ts] +function f(t: T, u: U, v: V, w: W) { + // right-deep structure (T (U (V W)) should get transformed to + // left-deep structure (((T U) V) W) + let x: spread(T, spread(U, spread(V, W))); + return x; +} + + +//// [spreadLeftDeep.js] +function f(t, u, v, w) { + // right-deep structure (T (U (V W)) should get transformed to + // left-deep structure (((T U) V) W) + var x; + return x; +} diff --git a/tests/baselines/reference/spreadLeftDeep.symbols b/tests/baselines/reference/spreadLeftDeep.symbols new file mode 100644 index 0000000000000..be7b16a1bf876 --- /dev/null +++ b/tests/baselines/reference/spreadLeftDeep.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/types/spread/spreadLeftDeep.ts === +function f(t: T, u: U, v: V, w: W) { +>f : Symbol(f, Decl(spreadLeftDeep.ts, 0, 0)) +>T : Symbol(T, Decl(spreadLeftDeep.ts, 0, 11)) +>U : Symbol(U, Decl(spreadLeftDeep.ts, 0, 13)) +>V : Symbol(V, Decl(spreadLeftDeep.ts, 0, 15)) +>W : Symbol(W, Decl(spreadLeftDeep.ts, 0, 17)) +>t : Symbol(t, Decl(spreadLeftDeep.ts, 0, 20)) +>T : Symbol(T, Decl(spreadLeftDeep.ts, 0, 11)) +>u : Symbol(u, Decl(spreadLeftDeep.ts, 0, 25)) +>U : Symbol(U, Decl(spreadLeftDeep.ts, 0, 13)) +>v : Symbol(v, Decl(spreadLeftDeep.ts, 0, 31)) +>V : Symbol(V, Decl(spreadLeftDeep.ts, 0, 15)) +>w : Symbol(w, Decl(spreadLeftDeep.ts, 0, 37)) +>W : Symbol(W, Decl(spreadLeftDeep.ts, 0, 17)) + + // right-deep structure (T (U (V W)) should get transformed to + // left-deep structure (((T U) V) W) + let x: spread(T, spread(U, spread(V, W))); +>x : Symbol(x, Decl(spreadLeftDeep.ts, 3, 7)) +>T : Symbol(T, Decl(spreadLeftDeep.ts, 0, 11)) +>U : Symbol(U, Decl(spreadLeftDeep.ts, 0, 13)) +>V : Symbol(V, Decl(spreadLeftDeep.ts, 0, 15)) +>W : Symbol(W, Decl(spreadLeftDeep.ts, 0, 17)) + + return x; +>x : Symbol(x, Decl(spreadLeftDeep.ts, 3, 7)) +} + diff --git a/tests/baselines/reference/spreadLeftDeep.types b/tests/baselines/reference/spreadLeftDeep.types new file mode 100644 index 0000000000000..27f2ac731360f --- /dev/null +++ b/tests/baselines/reference/spreadLeftDeep.types @@ -0,0 +1,29 @@ +=== tests/cases/conformance/types/spread/spreadLeftDeep.ts === +function f(t: T, u: U, v: V, w: W) { +>f : (t: T, u: U, v: V, w: W) => spread(spread(spread(T, U), V), W) +>T : T +>U : U +>V : V +>W : W +>t : T +>T : T +>u : U +>U : U +>v : V +>V : V +>w : W +>W : W + + // right-deep structure (T (U (V W)) should get transformed to + // left-deep structure (((T U) V) W) + let x: spread(T, spread(U, spread(V, W))); +>x : spread(spread(spread(T, U), V), W) +>T : T +>U : U +>V : V +>W : W + + return x; +>x : spread(spread(spread(T, U), V), W) +} + diff --git a/tests/cases/conformance/types/spread/interfaceSpread.ts b/tests/cases/conformance/types/spread/interfaceSpread.ts deleted file mode 100644 index e49fe412cecd3..0000000000000 --- 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 de2e49e676a39..605d192ddf772 100644 --- a/tests/cases/conformance/types/spread/objectSpread.ts +++ b/tests/cases/conformance/types/spread/objectSpread.ts @@ -82,7 +82,7 @@ let a = 12; let shortCutted: { a: number, b: string } = { ...o, a } // generics -function f(t: T, u: U): { ...T, ...U, id: string } { +function f(t: T, u: U): spread(spread(T, U), { id: string }) { return { ...t, ...u, id: 'id' }; } @@ -96,5 +96,5 @@ 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 } = +let classesAreWrong: spread(spread({ 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 index 8fa6363d2efca..44411904787a2 100644 --- a/tests/cases/conformance/types/spread/objectSpreadGeneric.ts +++ b/tests/cases/conformance/types/spread/objectSpreadGeneric.ts @@ -1,57 +1,57 @@ 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 + let o: spread(spread(T, U), V); + let uus: spread(U, U); + let us: spread(U); + const same: spread(spread(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 reversed: spread(spread(V, U), T) = o; // error, reversed + const reversed2: spread(spread(U, T), V) = o; // error, U and T are still reversed + const missingT: spread(U, V) = o; // error, missing T + const missingU: spread(T, V) = o; // error, missing U + const missingV: spread(T, U) = o; // error, missing V + const atEnd: spread(spread(T, U), { second: string }) = { ...t, ...u, second: 'foo' }; // ok + const atBeginning: spread(spread({ 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) + const emptySource: spread(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 } = + const unionCutoff: spread(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 } = + const interspersed: spread(spread(spread(spread({ 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 } = + const interspersedMissingU: spread(spread({ 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 } = + const interspersedOrder1: spread(spread(spread(spread({ 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 } = + const interspersedOrder2: spread(spread({ 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 } = + const mismatchFirst: spread(spread(spread(spread({ 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 } = + const mismatchSecond: spread(spread(spread(spread({ 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 } = + const mismatchLast: spread(spread(spread(spread({ 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 }; + let k1: spread(keyof T); + let k2: spread(keyof U); + let k3: spread(K); + let k4: spread(J); k1 = k1; // ok k2 = k2; // ok k1 = k2; // error @@ -63,8 +63,8 @@ function indexAccessedTest(t: T, u: k2 = k4; // error k4 = k2; // error - let i1: { ...T[K] }; - let i2: { ...U[J] }; + let i1: spread(T[K]); + let i2: spread(U[J]); i1 = i1; // ok i2 = i2; // ok i1 = i2; // error diff --git a/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts b/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts index 0f3555528d734..fe7f823c4739d 100644 --- a/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts +++ b/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts @@ -3,7 +3,7 @@ class C { c: boolean; } // index signatures are not allowed in object literals with spread types -let c: { ...C, b: string, c?: string, [n: number]: string }; +let c: spread(C, { b: string, c?: string, [n: number]: string }); let n: number = c.a; let s: string = c[12]; interface Indexed { @@ -16,13 +16,13 @@ interface Indexed2 { } let indexed: Indexed; let indexed2: Indexed2; -let i: { ...Indexed, b: number }; +let i: spread(Indexed, { b: number }); // only indexed has indexer, so i[101]: any i[101]; -let ii: { ...Indexed, ...Indexed2, b: boolean, d: number }; +let ii: spread(spread(Indexed, Indexed2), { b: boolean, d: number }); // both have indexer, so i[1001]: number | boolean let nb: number | boolean = ii[1001]; function f(t: T) { - let i: { ...T, [n: number]: string }; + let i: spread(T, { [n: number]: string }); } diff --git a/tests/cases/conformance/types/spread/objectSpreadInference.ts b/tests/cases/conformance/types/spread/objectSpreadInference.ts index a9c11187cca6a..ebc3b414f5b22 100644 --- a/tests/cases/conformance/types/spread/objectSpreadInference.ts +++ b/tests/cases/conformance/types/spread/objectSpreadInference.ts @@ -3,8 +3,8 @@ interface Result { 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 }; +declare function infer(tuv: spread(spread(T, U), { a: V })): { t: T, u: U, v: V }; +declare function infer2(utv: spread(spread(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" }); diff --git a/tests/cases/conformance/types/spread/objectSpreadIntersection.ts b/tests/cases/conformance/types/spread/objectSpreadIntersection.ts index 479faf13d0809..9b7e7a55fd4a4 100644 --- a/tests/cases/conformance/types/spread/objectSpreadIntersection.ts +++ b/tests/cases/conformance/types/spread/objectSpreadIntersection.ts @@ -2,7 +2,7 @@ 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; + let assignable: spread(spread(T | U, U & V), { id: string }) = result; } // concrete types work interface A1 { a: number } @@ -14,22 +14,22 @@ let b12: B1 & B2; let result = { ...a12, ...b12 }; let sn: number & string = result.a; sn = result.b; -let assignable: { ...(A1 & A2), ...(B1 & B2) } = result; +let assignable: spread(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; + let assignable: spread(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; + let assignable: spread(spread(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; + let assignable: spread(spread(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 17cb0f29a3b7d..ef9a565d754ce 100644 --- a/tests/cases/conformance/types/spread/objectSpreadNegative.ts +++ b/tests/cases/conformance/types/spread/objectSpreadNegative.ts @@ -8,7 +8,7 @@ class PrivateOptionalX { class PublicX { public x: number; } -let o2: { ...PublicX, ...PrivateOptionalX }; +let o2: spread(PublicX, PrivateOptionalX); let sn: number = o2.x; // error, x is private let optionalString: { sn?: string }; let optionalNumber: { sn?: number }; @@ -18,7 +18,7 @@ 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 spread: spread(Bool, Str) = { s: "foo" }; // error, missing 'b' let b: Bool; spread = b; // error, missing 's' @@ -55,14 +55,14 @@ 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) }; +let callableConstructableSpread: spread(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; + let tvs: spread(T & V); + let mistake: spread(T & U) = tvs; // { ...U } is not assignable to U return { ...initial, ...override }; } diff --git a/tests/cases/conformance/types/spread/objectSpreadScenarios.ts b/tests/cases/conformance/types/spread/objectSpreadScenarios.ts index 1db930cb71c51..43c1e37dc4d6c 100644 --- a/tests/cases/conformance/types/spread/objectSpreadScenarios.ts +++ b/tests/cases/conformance/types/spread/objectSpreadScenarios.ts @@ -1,12 +1,12 @@ interface A1 { a: boolean } interface B1 { b: number }; -function override(initial: U, override: U): { ...U, ...U } { +function override(initial: U, override: U): spread(U, U) { return { ...initial, ...override }; } -function update(this: { u: { ...U } }, override: U): void { +function update(this: { u: spread(U) }, override: U): void { this.u = { ...this.u, ...override }; } -function mixin(one: T, two: U): { ...T, ...U } { +function mixin(one: T, two: U): spread(T, U) { return { ...one, ...two }; } let a1: A1 = { a: true }; diff --git a/tests/cases/conformance/types/spread/objectSpreadUnion.ts b/tests/cases/conformance/types/spread/objectSpreadUnion.ts index 6f6cb1954ec61..deaf1561c35ef 100644 --- a/tests/cases/conformance/types/spread/objectSpreadUnion.ts +++ b/tests/cases/conformance/types/spread/objectSpreadUnion.ts @@ -4,18 +4,18 @@ interface A2 { a: string } let a12: A1 | A2; let result = { ...a12 }; let sn: number | string = result.a; -let assignable: { ...(A1 | A2) } = result; +let assignable: spread(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; + let expected: spread(T, { id: string }) | spread(U, { id: string }) | spread(V, { id: string }) = result; + let assignable: spread(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; + let expected: spread(spread(T, U), { id: string }) | spread(spread(T, V), { id: string }) | spread(U, { id: string }) | spread(spread(U, V), { id: string }); + let assignable: spread(spread(T | U, U | V), { id: string }) = result; } diff --git a/tests/cases/conformance/types/spread/spreadLeftDeep.ts b/tests/cases/conformance/types/spread/spreadLeftDeep.ts new file mode 100644 index 0000000000000..13af958239060 --- /dev/null +++ b/tests/cases/conformance/types/spread/spreadLeftDeep.ts @@ -0,0 +1,6 @@ +function f(t: T, u: U, v: V, w: W) { + // right-deep structure (T (U (V W)) should get transformed to + // left-deep structure (((T U) V) W) + let x: spread(T, spread(U, spread(V, W))); + return x; +} diff --git a/tests/cases/fourslash/findAllRefsForObjectSpread.ts b/tests/cases/fourslash/findAllRefsForObjectSpread.ts index 650324a5d8467..4a79ca4e2b3af 100644 --- a/tests/cases/fourslash/findAllRefsForObjectSpread.ts +++ b/tests/cases/fourslash/findAllRefsForObjectSpread.ts @@ -2,7 +2,7 @@ ////interface A1 { [|a|]: string }; ////interface A2 { [|a|]?: number }; -////let a12: { ...A1, ...A2 }; +////let a12: spread(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 64623c36cb76b..f4d0a089d8c07 100644 --- a/tests/cases/fourslash/goToDefinitionObjectSpread.ts +++ b/tests/cases/fourslash/goToDefinitionObjectSpread.ts @@ -2,6 +2,6 @@ ////interface A1 { /*1*/a: number }; ////interface A2 { /*2*/a?: number }; -////let a12: { ...A1, ...A2 }; +////let a12: spread(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 a2c640361e59c..14a4fb6056e18 100644 --- a/tests/cases/fourslash/renameObjectSpread.ts +++ b/tests/cases/fourslash/renameObjectSpread.ts @@ -2,7 +2,7 @@ ////interface A1 { [|a|]: number }; ////interface A2 { [|a|]?: number }; -////let a12: { ...A1, ...A2 }; +////let a12: spread(A1, A2); ////a12.[|a|]; const ranges = test.ranges(); verify.assertHasRanges(ranges); From a464f24f6fe6b3a43edf2a5e7fd52e847bfde319 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 12 Jan 2017 12:53:02 -0800 Subject: [PATCH 6/9] Fix lint in parser.ts --- src/compiler/parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 09bdab6936dd5..4a71d16a148cd 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2615,7 +2615,7 @@ namespace ts { parseExpected(SyntaxKind.SpreadKeyword); parseExpected(SyntaxKind.OpenParenToken); node.left = parseType(); - if(parseOptional(SyntaxKind.CommaToken)) { + if (parseOptional(SyntaxKind.CommaToken)) { node.right = parseType(); } parseExpected(SyntaxKind.CloseParenToken); From 7a2d0ca745cf1bf7f0b03e3fab575097f708b34e Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 25 Jan 2017 11:55:03 -0800 Subject: [PATCH 7/9] getRootSymbols gets all root symbols of a spread symbol Previously it would only get the top two. --- src/compiler/checker.ts | 9 +++++++-- .../fourslash/findAllRefsForObjectSpread.ts | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 95e88fcba9927..884a1a23583a6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20430,8 +20430,13 @@ namespace ts { } else if (symbol.flags & SymbolFlags.Transient) { if ((symbol as SymbolLinks).leftSpread) { - const links = symbol as SymbolLinks; - return [links.leftSpread, links.rightSpread]; + const symbols = []; + while ((symbol as SymbolLinks).leftSpread) { + symbols.push((symbol as SymbolLinks).rightSpread); + symbol = (symbol as SymbolLinks).leftSpread; + } + symbols.push(symbol); + return symbols; } if ((symbol as SymbolLinks).mappedTypeOrigin) { return getRootSymbols((symbol as SymbolLinks).mappedTypeOrigin); diff --git a/tests/cases/fourslash/findAllRefsForObjectSpread.ts b/tests/cases/fourslash/findAllRefsForObjectSpread.ts index 4a79ca4e2b3af..0aea4e1a0cd0c 100644 --- a/tests/cases/fourslash/findAllRefsForObjectSpread.ts +++ b/tests/cases/fourslash/findAllRefsForObjectSpread.ts @@ -2,11 +2,18 @@ ////interface A1 { [|a|]: string }; ////interface A2 { [|a|]?: number }; -////let a12: spread(A1, A2); -////a12.[|a|]; +////interface A3 { [|a|]?: boolean }; +////let a123: spread(spread(A1, A2), A3); +////a123.[|a|]; const ranges = test.ranges(); + // members of spread types only refer to themselves and the resulting property -verify.referencesOf(ranges[0], [ranges[0], ranges[2]]); -verify.referencesOf(ranges[1], [ranges[1], ranges[2]]); +verifyReferencesOfIndices(ranges, 0, [0, 3]); +verifyReferencesOfIndices(ranges, 1, [1, 3]); +verifyReferencesOfIndices(ranges, 2, [2, 3]); // but the resulting property refers to everything -verify.referencesOf(ranges[2], ranges); +verifyReferencesOfIndices(ranges, 3, [0, 1, 2, 3]); + +function verifyReferencesOfIndices(ranges: FourSlashInterface.Range[], source: number, ns: number[]) { + verify.referencesOf(ranges[source], ns.map(n => ranges[n])); +} From c1a5482a2be94c8eb0cdec9d086b529f5ff2dc83 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 27 Jan 2017 08:59:01 -0800 Subject: [PATCH 8/9] Improve use of maps in spread type cache --- src/compiler/checker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 884a1a23583a6..da675db601c90 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6407,9 +6407,10 @@ namespace ts { if (right.flags & TypeFlags.Object && left.flags & TypeFlags.Object) { return createSpreadType(left, right); } - const spread = spreadTypes.set(id, createType(TypeFlags.Spread) as SpreadType).get(id); + const spread = createType(TypeFlags.Spread) as SpreadType spread.left = left as SpreadType | ResolvedType; spread.right = right as TypeParameter | IntersectionType | IndexType | IndexedAccessType | ResolvedType; + spreadTypes.set(id, spread); return spread; } From 0a9c179dee592d960b0bdb970b757674f6462138 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 27 Jan 2017 15:13:50 -0800 Subject: [PATCH 9/9] Remove unused SyntheticSymbolKind type. I missed this in the object-spread PR. --- src/compiler/types.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ca23f86da1ef8..b7ea3d0c92ea8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2499,12 +2499,6 @@ CannotBeNamed } - /* @internal */ - export const enum SyntheticSymbolKind { - UnionOrIntersection, - Spread - } - export const enum TypePredicateKind { This, Identifier