From 6007c17eabfb4ff1d62715585261e9474cee2db7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 5 Feb 2020 16:10:47 -0800 Subject: [PATCH 01/11] add tests but not baselines or fixes --- .../conformance/types/spread/objectSpread.ts | 13 ------------- .../types/spread/objectSpreadNegative.ts | 16 ++++++++++++++++ .../types/spread/spreadOverwritesProperty.ts | 11 +++++++++++ .../spread/spreadOverwritesPropertyStrict.ts | 12 ++++++++++++ 4 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 tests/cases/conformance/types/spread/spreadOverwritesProperty.ts create mode 100644 tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts diff --git a/tests/cases/conformance/types/spread/objectSpread.ts b/tests/cases/conformance/types/spread/objectSpread.ts index 5917bdf6dcf95..7d4ed52983e1f 100644 --- a/tests/cases/conformance/types/spread/objectSpread.ts +++ b/tests/cases/conformance/types/spread/objectSpread.ts @@ -8,23 +8,14 @@ let addAfter: { a: number, b: string, c: boolean } = { ...o, c: false } let addBefore: { a: number, b: string, c: boolean } = { c: false, ...o } -// Note: ignore still changes the order that properties are printed -let ignore: { a: number, b: string } = - { b: 'ignored', ...o } let override: { a: number, b: string } = { ...o, b: 'override' } let nested: { a: number, b: boolean, c: string } = { ...{ a: 3, ...{ b: false, c: 'overriden' } }, c: 'whatever' } let combined: { a: number, b: string, c: boolean } = { ...o, ...o2 } -let combinedBefore: { a: number, b: string, c: boolean } = - { b: 'ok', ...o, ...o2 } -let combinedMid: { a: number, b: string, c: boolean } = - { ...o, b: 'ok', ...o2 } let combinedAfter: { a: number, b: string, c: boolean } = { ...o, ...o2, b: 'ok' } -let combinedNested: { a: number, b: boolean, c: string, d: string } = - { ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } let combinedNestedChangeType: { a: number, b: boolean, c: number } = { ...{ a: 1, ...{ b: false, c: 'overriden' } }, c: -1 } let propertyNested: { a: { a: number, b: string } } = @@ -92,8 +83,6 @@ cplus.plus(); // new field's type conflicting with existing field is OK let changeTypeAfter: { a: string, b: string } = { ...o, a: 'wrong type?' } -let changeTypeBefore: { a: number, b: string } = - { a: 'wrong type?', ...o }; let changeTypeBoth: { a: string, b: number } = { ...o, ...swap }; @@ -110,8 +99,6 @@ function container( // computed property let computedFirst: { a: number, b: string, "before everything": number } = { ['before everything']: 12, ...o, b: 'yes' } - let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = - { ...o, ['in the middle']: 13, b: 'maybe?', ...o2 } let computedAfter: { a: number, b: string, "at the end": number } = { ...o, b: 'yeah', ['at the end']: 14 } } diff --git a/tests/cases/conformance/types/spread/objectSpreadNegative.ts b/tests/cases/conformance/types/spread/objectSpreadNegative.ts index f31d62e2faf19..dfc902748ecb9 100644 --- a/tests/cases/conformance/types/spread/objectSpreadNegative.ts +++ b/tests/cases/conformance/types/spread/objectSpreadNegative.ts @@ -28,6 +28,22 @@ 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 } +// Note: ignore changes the order that properties are printed +let ignore: { a: number, b: string } = + { b: 'ignored', ...o } + +let o3 = { a: 1, b: 'no' } +let o4 = { b: 'yes', c: true } +let combinedBefore: { a: number, b: string, c: boolean } = + { b: 'ok', ...o3, ...o4 } +let combinedMid: { a: number, b: string, c: boolean } = + { ...o3, b: 'ok', ...o4 } +let combinedNested: { a: number, b: boolean, c: string, d: string } = + { ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } +let changeTypeBefore: { a: number, b: string } = + { a: 'wrong type?', ...o3 }; +let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = + { ...o3, ['in the middle']: 13, b: 'maybe?', ...o4 } // primitives are not allowed, except for falsy ones let spreadNum = { ...12 }; diff --git a/tests/cases/conformance/types/spread/spreadOverwritesProperty.ts b/tests/cases/conformance/types/spread/spreadOverwritesProperty.ts new file mode 100644 index 0000000000000..909fe5434f68c --- /dev/null +++ b/tests/cases/conformance/types/spread/spreadOverwritesProperty.ts @@ -0,0 +1,11 @@ +declare var ab: { a: number, b: number }; +declare var abq: { a: number, b?: number }; +var unused1 = { b: 1, ...ab } +var unused2 = { ...ab, ...ab } +var unused3 = { b: 1, ...abq } + +function g(obj: { x: number | undefined }) { + return { x: 1, ...obj }; // should be allowed because of undefined +} +function h(obj: { x: number }) { + return { x: 1, ...obj }; // should be allowed because we don't know about undefined diff --git a/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts b/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts new file mode 100644 index 0000000000000..e2bf6da240fac --- /dev/null +++ b/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts @@ -0,0 +1,12 @@ +// @strict: true +declare var ab: { a: number, b: number }; +declare var abq: { a: number, b?: number }; +var unused1 = { b: 1, ...ab } +var unused2 = { ...ab, ...ab } +var unused3 = { b: 1, ...abq } +function g(obj: { x: number | undefined }) { + return { x: 1, ...obj }; // should be allowed because of undefined +} +function f(obj: { x: number } | undefined) { + return { x: 1, ...obj }; +} From 321039046e47ab48f2ba87375433737a885b6154 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 7 Feb 2020 17:03:25 -0800 Subject: [PATCH 02/11] Update original change Still probably wrong; probably doesn't even compile beacuse I'm just typing on my laptop. --- src/compiler/checker.ts | 35 ++++++++++++++-------------- src/compiler/diagnosticMessages.json | 6 ++++- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index eb09a619eca34..21c5f5c9a8d66 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12978,7 +12978,7 @@ namespace ts { * this function should be called in a left folding style, with left = previous result of getSpreadType * and right = the new element to be spread. */ - function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, objectFlags: ObjectFlags, readonly: boolean): Type { + function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, objectFlags: ObjectFlags, readonly: boolean, isUnion?: boolean): Type { if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } @@ -12994,16 +12994,16 @@ namespace ts { if (left.flags & TypeFlags.Union) { const merged = tryMergeUnionOfObjectTypeAndEmptyObject(left as UnionType, readonly); if (merged) { - return getSpreadType(merged, right, symbol, objectFlags, readonly); + return getSpreadType(merged, right, symbol, objectFlags, readonly, isUnion); } - return mapType(left, t => getSpreadType(t, right, symbol, objectFlags, readonly)); + return mapType(left, t => getSpreadType(t, right, symbol, objectFlags, readonly, isUnion)); } if (right.flags & TypeFlags.Union) { const merged = tryMergeUnionOfObjectTypeAndEmptyObject(right as UnionType, readonly); if (merged) { - return getSpreadType(left, merged, symbol, objectFlags, readonly); + return getSpreadType(left, merged, symbol, objectFlags, readonly, isUnion); } - return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly)); + return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly, /*isUnion*/ true)); } if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) { return left; @@ -13067,6 +13067,14 @@ namespace ts { result.nameType = getSymbolLinks(leftProp).nameType; members.set(leftProp.escapedName, result); } + else if (strictNullChecks && + !isUnion && + symbol && + !isFromSpreadAssignment(leftProp, symbol) && + isFromSpreadAssignment(rightProp, symbol) && + !(getFalsyFlags(rightType) & TypeFlags.Nullable)) { + error(leftProp.valueDeclaration, Diagnostics.0_is_unused_because_a_subsequent_spread_overwrites_it); + } } else { members.set(leftProp.escapedName, getSpreadSymbol(leftProp, readonly)); @@ -16561,6 +16569,10 @@ namespace ts { return match === -1 || discriminable.indexOf(/*searchElement*/ true, match + 1) !== -1 ? defaultValue : target.types[match]; } + function isFromSpreadAssignment(prop: Symbol, container: Symbol) { + return !(prop.valueDeclaration && container.valueDeclaration && prop.valueDeclaration.parent === container.valueDeclaration); + } + /** * A type is 'weak' if it is an object type with at least one optional property * and no required properties, call/construct signatures or index signatures @@ -22605,7 +22617,6 @@ namespace ts { let spread: Type = emptyJsxObjectType; let hasSpreadAnyType = false; let typeToIntersect: Type | undefined; - let explicitlySpecifyChildrenAttribute = false; let objectFlags: ObjectFlags = ObjectFlags.JsxAttributes; const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement)); @@ -22624,9 +22635,6 @@ namespace ts { attributeSymbol.type = exprType; attributeSymbol.target = member; attributesTable.set(attributeSymbol.escapedName, attributeSymbol); - if (attributeDecl.name.escapedText === jsxChildrenPropertyName) { - explicitlySpecifyChildrenAttribute = true; - } } else { Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute); @@ -22660,13 +22668,6 @@ namespace ts { const childrenTypes: Type[] = checkJsxChildren(parent, checkMode); if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") { - // Error if there is a attribute named "children" explicitly specified and children element. - // This is because children element will overwrite the value from attributes. - // Note: we will not warn "children" attribute overwritten if "children" attribute is specified in object spread. - if (explicitlySpecifyChildrenAttribute) { - error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, unescapeLeadingUnderscores(jsxChildrenPropertyName)); - } - const contextualType = getApparentTypeOfContextualType(openingLikeElement.attributes); const childrenContextualType = contextualType && getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName); // If there are children in the body of JSX element, create dummy attribute "children" with the union of children types so that it will pass the attribute checking process @@ -25119,7 +25120,7 @@ namespace ts { if (node.arguments.length === 1) { const text = getSourceFileOfNode(node).text; if (isLineBreak(text.charCodeAt(skipTrivia(text, node.expression.end, /* stopAfterLineBreak */ true) - 1))) { - relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.It_is_highly_likely_that_you_are_missing_a_semicolon); + relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.Are_you_missing_a_semicolon_here); } } invocationError(node.expression, apparentType, SignatureKind.Call, relatedInformation); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 2dc894e71fb50..6529d1a8d426a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2683,7 +2683,7 @@ "category": "Error", "code": 2733 }, - "It is highly likely that you are missing a semicolon.": { + "Are you missing a semicolon here?": { "category": "Error", "code": 2734 }, @@ -2879,6 +2879,10 @@ "category": "Message", "code": 2782 }, + "'{0}' is unused because a subsequent spread overwrites it.": { + "category": "Error", + "code": 2783 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", From 66c5613357ca6a19adf6ef41f8614e7620c7639f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 7 Feb 2020 17:10:00 -0800 Subject: [PATCH 03/11] fix error code ok --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 21c5f5c9a8d66..b60720f1a4d5d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13073,7 +13073,7 @@ namespace ts { !isFromSpreadAssignment(leftProp, symbol) && isFromSpreadAssignment(rightProp, symbol) && !(getFalsyFlags(rightType) & TypeFlags.Nullable)) { - error(leftProp.valueDeclaration, Diagnostics.0_is_unused_because_a_subsequent_spread_overwrites_it); + error(leftProp.valueDeclaration, Diagnostics._0_is_unused_because_a_subsequent_spread_overwrites_it); } } else { From 59eb5b9b72fa6bbe2f8509c7e02e55a77f745a30 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 10 Feb 2020 08:45:16 -0800 Subject: [PATCH 04/11] notes to self --- src/compiler/checker.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b60720f1a4d5d..28ae0980a70c1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13001,8 +13001,11 @@ namespace ts { if (right.flags & TypeFlags.Union) { const merged = tryMergeUnionOfObjectTypeAndEmptyObject(right as UnionType, readonly); if (merged) { + // TODO: I don't really think this needs to be recursive but maybe??? return getSpreadType(left, merged, symbol, objectFlags, readonly, isUnion); } + // TODO: Only isUnion if one element is undefined! (it should be easy to construct a failing test case for this) + // (isUnion is a bad name btw) return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly, /*isUnion*/ true)); } if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) { From 4bb55c9b4c0eedaaba6a697533103d305c64edba Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 10 Feb 2020 15:23:09 -0800 Subject: [PATCH 05/11] Error: property is specified more than once via spread --- src/compiler/checker.ts | 20 +- src/compiler/diagnosticMessages.json | 4 +- .../betterErrorForAccidentalCall.errors.txt | 6 +- .../checkJsxChildrenProperty13.errors.txt | 33 - .../checkJsxChildrenProperty2.errors.txt | 5 +- tests/baselines/reference/objectSpread.js | 24 +- .../baselines/reference/objectSpread.symbols | 678 ++++++++---------- tests/baselines/reference/objectSpread.types | 91 --- .../reference/objectSpreadNegative.errors.txt | 77 +- .../reference/objectSpreadNegative.js | 38 +- .../reference/objectSpreadNegative.symbols | 170 +++-- .../reference/objectSpreadNegative.types | 131 +++- .../reference/spreadOverwritesProperty.js | 37 + .../spreadOverwritesProperty.symbols | 46 ++ .../reference/spreadOverwritesProperty.types | 55 ++ .../spreadOverwritesPropertyStrict.errors.txt | 24 + .../spreadOverwritesPropertyStrict.js | 42 ++ .../spreadOverwritesPropertyStrict.symbols | 55 ++ .../spreadOverwritesPropertyStrict.types | 66 ++ .../types/spread/objectSpreadNegative.ts | 9 +- .../types/spread/spreadOverwritesProperty.ts | 6 +- .../spread/spreadOverwritesPropertyStrict.ts | 13 +- 22 files changed, 996 insertions(+), 634 deletions(-) delete mode 100644 tests/baselines/reference/checkJsxChildrenProperty13.errors.txt create mode 100644 tests/baselines/reference/spreadOverwritesProperty.js create mode 100644 tests/baselines/reference/spreadOverwritesProperty.symbols create mode 100644 tests/baselines/reference/spreadOverwritesProperty.types create mode 100644 tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt create mode 100644 tests/baselines/reference/spreadOverwritesPropertyStrict.js create mode 100644 tests/baselines/reference/spreadOverwritesPropertyStrict.symbols create mode 100644 tests/baselines/reference/spreadOverwritesPropertyStrict.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index aad560d5074cf..215b7dda41f19 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13032,7 +13032,7 @@ namespace ts { * this function should be called in a left folding style, with left = previous result of getSpreadType * and right = the new element to be spread. */ - function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, objectFlags: ObjectFlags, readonly: boolean, isUnion?: boolean): Type { + function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, objectFlags: ObjectFlags, readonly: boolean, isParentTypeNullable?: boolean): Type { if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } @@ -13048,19 +13048,16 @@ namespace ts { if (left.flags & TypeFlags.Union) { const merged = tryMergeUnionOfObjectTypeAndEmptyObject(left as UnionType, readonly); if (merged) { - return getSpreadType(merged, right, symbol, objectFlags, readonly, isUnion); + return getSpreadType(merged, right, symbol, objectFlags, readonly, isParentTypeNullable); } - return mapType(left, t => getSpreadType(t, right, symbol, objectFlags, readonly, isUnion)); + return mapType(left, t => getSpreadType(t, right, symbol, objectFlags, readonly, isParentTypeNullable)); } if (right.flags & TypeFlags.Union) { const merged = tryMergeUnionOfObjectTypeAndEmptyObject(right as UnionType, readonly); if (merged) { - // TODO: I don't really think this needs to be recursive but maybe??? - return getSpreadType(left, merged, symbol, objectFlags, readonly, isUnion); + return getSpreadType(left, merged, symbol, objectFlags, readonly, !!(right.flags & TypeFlags.Nullable)); } - // TODO: Only isUnion if one element is undefined! (it should be easy to construct a failing test case for this) - // (isUnion is a bad name btw) - return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly, /*isUnion*/ true)); + return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly, !!(right.flags & TypeFlags.Nullable))); } if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) { return left; @@ -13125,12 +13122,12 @@ namespace ts { members.set(leftProp.escapedName, result); } else if (strictNullChecks && - !isUnion && + !isParentTypeNullable && symbol && !isFromSpreadAssignment(leftProp, symbol) && isFromSpreadAssignment(rightProp, symbol) && !(getFalsyFlags(rightType) & TypeFlags.Nullable)) { - error(leftProp.valueDeclaration, Diagnostics._0_is_unused_because_a_subsequent_spread_overwrites_it); + error(leftProp.valueDeclaration, Diagnostics._0_is_specified_more_than_once_so_this_usage_will_be_overwritten, unescapeLeadingUnderscores(leftProp.escapedName)); } } else { @@ -16632,6 +16629,7 @@ namespace ts { } function isFromSpreadAssignment(prop: Symbol, container: Symbol) { + // TODO: Should use ?. now return !(prop.valueDeclaration && container.valueDeclaration && prop.valueDeclaration.parent === container.valueDeclaration); } @@ -25182,7 +25180,7 @@ namespace ts { if (node.arguments.length === 1) { const text = getSourceFileOfNode(node).text; if (isLineBreak(text.charCodeAt(skipTrivia(text, node.expression.end, /* stopAfterLineBreak */ true) - 1))) { - relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.Are_you_missing_a_semicolon_here); + relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.Are_you_missing_a_semicolon); } } invocationError(node.expression, apparentType, SignatureKind.Call, relatedInformation); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 6529d1a8d426a..961f2dfbe6e1f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2683,7 +2683,7 @@ "category": "Error", "code": 2733 }, - "Are you missing a semicolon here?": { + "Are you missing a semicolon?": { "category": "Error", "code": 2734 }, @@ -2879,7 +2879,7 @@ "category": "Message", "code": 2782 }, - "'{0}' is unused because a subsequent spread overwrites it.": { + "'{0}' is specified more than once, so this usage will be overwritten.": { "category": "Error", "code": 2783 }, diff --git a/tests/baselines/reference/betterErrorForAccidentalCall.errors.txt b/tests/baselines/reference/betterErrorForAccidentalCall.errors.txt index 46b359017e0bd..e381b522ec792 100644 --- a/tests/baselines/reference/betterErrorForAccidentalCall.errors.txt +++ b/tests/baselines/reference/betterErrorForAccidentalCall.errors.txt @@ -27,20 +27,20 @@ tests/cases/compiler/betterErrorForAccidentalCall.ts(13,1): error TS2349: This e ~~~~~ !!! error TS2349: This expression is not callable. !!! error TS2349: Type 'String' has no call signatures. -!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:7:1: It is highly likely that you are missing a semicolon. +!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:7:1: Are you missing a semicolon here? (1 as number).toString(); foo() ~~~~~ !!! error TS2349: This expression is not callable. !!! error TS2349: Type 'String' has no call signatures. -!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:10:1: It is highly likely that you are missing a semicolon. +!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:10:1: Are you missing a semicolon here? (1 + 2).toString(); foo() ~~~~~ !!! error TS2349: This expression is not callable. !!! error TS2349: Type 'String' has no call signatures. -!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:13:1: It is highly likely that you are missing a semicolon. +!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:13:1: Are you missing a semicolon here? (1).toString(); \ No newline at end of file diff --git a/tests/baselines/reference/checkJsxChildrenProperty13.errors.txt b/tests/baselines/reference/checkJsxChildrenProperty13.errors.txt deleted file mode 100644 index c926980cab11f..0000000000000 --- a/tests/baselines/reference/checkJsxChildrenProperty13.errors.txt +++ /dev/null @@ -1,33 +0,0 @@ -tests/cases/conformance/jsx/file.tsx(12,30): error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. - - -==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== - import React = require('react'); - - interface ButtonProp { - a: number, - b: string, - children: Button; - } - - class Button extends React.Component { - render() { - // Error children are specified twice - return ( - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. -
Hello World
-
); - } - } - - interface InnerButtonProp { - a: number - } - - class InnerButton extends React.Component { - render() { - return (); - } - } - \ No newline at end of file diff --git a/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt b/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt index b289fb97d2bba..323f277e09bb1 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt +++ b/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt @@ -1,12 +1,11 @@ tests/cases/conformance/jsx/file.tsx(14,10): error TS2741: Property 'children' is missing in type '{ a: number; b: string; }' but required in type 'Prop'. -tests/cases/conformance/jsx/file.tsx(17,11): error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. tests/cases/conformance/jsx/file.tsx(31,6): error TS2746: This JSX tag's 'children' prop expects a single child of type 'string | Element', but multiple children were provided. tests/cases/conformance/jsx/file.tsx(37,6): error TS2746: This JSX tag's 'children' prop expects a single child of type 'string | Element', but multiple children were provided. tests/cases/conformance/jsx/file.tsx(43,6): error TS2746: This JSX tag's 'children' prop expects a single child of type 'string | Element', but multiple children were provided. tests/cases/conformance/jsx/file.tsx(49,6): error TS2746: This JSX tag's 'children' prop expects a single child of type 'string | Element', but multiple children were provided. -==== tests/cases/conformance/jsx/file.tsx (6 errors) ==== +==== tests/cases/conformance/jsx/file.tsx (5 errors) ==== import React = require('react'); interface Prop { @@ -27,8 +26,6 @@ tests/cases/conformance/jsx/file.tsx(49,6): error TS2746: This JSX tag's 'childr let k0 = - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. hi hi hi! ; diff --git a/tests/baselines/reference/objectSpread.js b/tests/baselines/reference/objectSpread.js index 1265cc889ff79..0aa167974edbb 100644 --- a/tests/baselines/reference/objectSpread.js +++ b/tests/baselines/reference/objectSpread.js @@ -7,23 +7,14 @@ let addAfter: { a: number, b: string, c: boolean } = { ...o, c: false } let addBefore: { a: number, b: string, c: boolean } = { c: false, ...o } -// Note: ignore still changes the order that properties are printed -let ignore: { a: number, b: string } = - { b: 'ignored', ...o } let override: { a: number, b: string } = { ...o, b: 'override' } let nested: { a: number, b: boolean, c: string } = { ...{ a: 3, ...{ b: false, c: 'overriden' } }, c: 'whatever' } let combined: { a: number, b: string, c: boolean } = { ...o, ...o2 } -let combinedBefore: { a: number, b: string, c: boolean } = - { b: 'ok', ...o, ...o2 } -let combinedMid: { a: number, b: string, c: boolean } = - { ...o, b: 'ok', ...o2 } let combinedAfter: { a: number, b: string, c: boolean } = { ...o, ...o2, b: 'ok' } -let combinedNested: { a: number, b: boolean, c: string, d: string } = - { ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } let combinedNestedChangeType: { a: number, b: boolean, c: number } = { ...{ a: 1, ...{ b: false, c: 'overriden' } }, c: -1 } let propertyNested: { a: { a: number, b: string } } = @@ -91,8 +82,6 @@ cplus.plus(); // new field's type conflicting with existing field is OK let changeTypeAfter: { a: string, b: string } = { ...o, a: 'wrong type?' } -let changeTypeBefore: { a: number, b: string } = - { a: 'wrong type?', ...o }; let changeTypeBoth: { a: string, b: number } = { ...o, ...swap }; @@ -109,8 +98,6 @@ function container( // computed property let computedFirst: { a: number, b: string, "before everything": number } = { ['before everything']: 12, ...o, b: 'yes' } - let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = - { ...o, ['in the middle']: 13, b: 'maybe?', ...o2 } let computedAfter: { a: number, b: string, "at the end": number } = { ...o, b: 'yeah', ['at the end']: 14 } } @@ -173,15 +160,10 @@ var o2 = { b: 'yes', c: true }; var swap = { a: 'yes', b: -1 }; var addAfter = __assign(__assign({}, o), { c: false }); var addBefore = __assign({ c: false }, o); -// Note: ignore still changes the order that properties are printed -var ignore = __assign({ b: 'ignored' }, o); var override = __assign(__assign({}, o), { b: 'override' }); var nested = __assign(__assign({}, __assign({ a: 3 }, { b: false, c: 'overriden' })), { c: 'whatever' }); var combined = __assign(__assign({}, o), o2); -var combinedBefore = __assign(__assign({ b: 'ok' }, o), o2); -var combinedMid = __assign(__assign(__assign({}, o), { b: 'ok' }), o2); var combinedAfter = __assign(__assign(__assign({}, o), o2), { b: 'ok' }); -var combinedNested = __assign(__assign(__assign({}, __assign({ a: 4 }, { b: false, c: 'overriden' })), { d: 'actually new' }), { a: 5, d: 'maybe new' }); var combinedNestedChangeType = __assign(__assign({}, __assign({ a: 1 }, { b: false, c: 'overriden' })), { c: -1 }); var propertyNested = { a: __assign({}, o) }; // accessors don't copy the descriptor @@ -231,18 +213,16 @@ var cplus = __assign(__assign({}, c), { plus: function () { return this.p + 1; } cplus.plus(); // new field's type conflicting with existing field is OK var changeTypeAfter = __assign(__assign({}, o), { a: 'wrong type?' }); -var changeTypeBefore = __assign({ a: 'wrong type?' }, o); var changeTypeBoth = __assign(__assign({}, o), swap); // optional function container(definiteBoolean, definiteString, optionalString, optionalNumber) { - var _a, _b, _c; + var _a, _b; var optionalUnionStops = __assign(__assign(__assign({}, definiteBoolean), definiteString), optionalNumber); var optionalUnionDuplicates = __assign(__assign(__assign(__assign({}, definiteBoolean), definiteString), optionalString), optionalNumber); var allOptional = __assign(__assign({}, optionalString), optionalNumber); // computed property var computedFirst = __assign(__assign((_a = {}, _a['before everything'] = 12, _a), o), { b: 'yes' }); - var computedMiddle = __assign(__assign(__assign({}, o), (_b = {}, _b['in the middle'] = 13, _b.b = 'maybe?', _b)), o2); - var computedAfter = __assign(__assign({}, o), (_c = { b: 'yeah' }, _c['at the end'] = 14, _c)); + var computedAfter = __assign(__assign({}, o), (_b = { b: 'yeah' }, _b['at the end'] = 14, _b)); } // shortcut syntax var a = 12; diff --git a/tests/baselines/reference/objectSpread.symbols b/tests/baselines/reference/objectSpread.symbols index e72772676e114..c663cb4f58098 100644 --- a/tests/baselines/reference/objectSpread.symbols +++ b/tests/baselines/reference/objectSpread.symbols @@ -34,324 +34,268 @@ let addBefore: { a: number, b: string, c: boolean } = >c : Symbol(c, Decl(objectSpread.ts, 7, 5)) >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) -// Note: ignore still changes the order that properties are printed -let ignore: { a: number, b: string } = ->ignore : Symbol(ignore, Decl(objectSpread.ts, 9, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 9, 13)) ->b : Symbol(b, Decl(objectSpread.ts, 9, 24)) - - { b: 'ignored', ...o } ->b : Symbol(b, Decl(objectSpread.ts, 10, 5)) ->o : Symbol(o, Decl(objectSpread.ts, 0, 3)) - let override: { a: number, b: string } = ->override : Symbol(override, Decl(objectSpread.ts, 11, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 11, 15)) ->b : Symbol(b, Decl(objectSpread.ts, 11, 26)) +>override : Symbol(override, Decl(objectSpread.ts, 8, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 8, 15)) +>b : Symbol(b, Decl(objectSpread.ts, 8, 26)) { ...o, b: 'override' } >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->b : Symbol(b, Decl(objectSpread.ts, 12, 11)) +>b : Symbol(b, Decl(objectSpread.ts, 9, 11)) let nested: { a: number, b: boolean, c: string } = ->nested : Symbol(nested, Decl(objectSpread.ts, 13, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 13, 13)) ->b : Symbol(b, Decl(objectSpread.ts, 13, 24)) ->c : Symbol(c, Decl(objectSpread.ts, 13, 36)) +>nested : Symbol(nested, Decl(objectSpread.ts, 10, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 10, 13)) +>b : Symbol(b, Decl(objectSpread.ts, 10, 24)) +>c : Symbol(c, Decl(objectSpread.ts, 10, 36)) { ...{ a: 3, ...{ b: false, c: 'overriden' } }, c: 'whatever' } ->a : Symbol(a, Decl(objectSpread.ts, 14, 10)) ->b : Symbol(b, Decl(objectSpread.ts, 14, 21)) ->c : Symbol(c, Decl(objectSpread.ts, 14, 31)) ->c : Symbol(c, Decl(objectSpread.ts, 14, 51)) +>a : Symbol(a, Decl(objectSpread.ts, 11, 10)) +>b : Symbol(b, Decl(objectSpread.ts, 11, 21)) +>c : Symbol(c, Decl(objectSpread.ts, 11, 31)) +>c : Symbol(c, Decl(objectSpread.ts, 11, 51)) let combined: { a: number, b: string, c: boolean } = ->combined : Symbol(combined, Decl(objectSpread.ts, 15, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 15, 15)) ->b : Symbol(b, Decl(objectSpread.ts, 15, 26)) ->c : Symbol(c, Decl(objectSpread.ts, 15, 37)) +>combined : Symbol(combined, Decl(objectSpread.ts, 12, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 12, 15)) +>b : Symbol(b, Decl(objectSpread.ts, 12, 26)) +>c : Symbol(c, Decl(objectSpread.ts, 12, 37)) { ...o, ...o2 } >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) >o2 : Symbol(o2, Decl(objectSpread.ts, 1, 3)) -let combinedBefore: { a: number, b: string, c: boolean } = ->combinedBefore : Symbol(combinedBefore, Decl(objectSpread.ts, 17, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 17, 21)) ->b : Symbol(b, Decl(objectSpread.ts, 17, 32)) ->c : Symbol(c, Decl(objectSpread.ts, 17, 43)) - - { b: 'ok', ...o, ...o2 } ->b : Symbol(b, Decl(objectSpread.ts, 18, 5)) ->o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->o2 : Symbol(o2, Decl(objectSpread.ts, 1, 3)) - -let combinedMid: { a: number, b: string, c: boolean } = ->combinedMid : Symbol(combinedMid, Decl(objectSpread.ts, 19, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 19, 18)) ->b : Symbol(b, Decl(objectSpread.ts, 19, 29)) ->c : Symbol(c, Decl(objectSpread.ts, 19, 40)) - - { ...o, b: 'ok', ...o2 } ->o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->b : Symbol(b, Decl(objectSpread.ts, 20, 11)) ->o2 : Symbol(o2, Decl(objectSpread.ts, 1, 3)) - let combinedAfter: { a: number, b: string, c: boolean } = ->combinedAfter : Symbol(combinedAfter, Decl(objectSpread.ts, 21, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 21, 20)) ->b : Symbol(b, Decl(objectSpread.ts, 21, 31)) ->c : Symbol(c, Decl(objectSpread.ts, 21, 42)) +>combinedAfter : Symbol(combinedAfter, Decl(objectSpread.ts, 14, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 14, 20)) +>b : Symbol(b, Decl(objectSpread.ts, 14, 31)) +>c : Symbol(c, Decl(objectSpread.ts, 14, 42)) { ...o, ...o2, b: 'ok' } >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) >o2 : Symbol(o2, Decl(objectSpread.ts, 1, 3)) ->b : Symbol(b, Decl(objectSpread.ts, 22, 18)) - -let combinedNested: { a: number, b: boolean, c: string, d: string } = ->combinedNested : Symbol(combinedNested, Decl(objectSpread.ts, 23, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 23, 21)) ->b : Symbol(b, Decl(objectSpread.ts, 23, 32)) ->c : Symbol(c, Decl(objectSpread.ts, 23, 44)) ->d : Symbol(d, Decl(objectSpread.ts, 23, 55)) - - { ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } ->a : Symbol(a, Decl(objectSpread.ts, 24, 10)) ->b : Symbol(b, Decl(objectSpread.ts, 24, 21)) ->c : Symbol(c, Decl(objectSpread.ts, 24, 31)) ->d : Symbol(d, Decl(objectSpread.ts, 24, 51)) ->a : Symbol(a, Decl(objectSpread.ts, 24, 75)) ->d : Symbol(d, Decl(objectSpread.ts, 24, 81)) +>b : Symbol(b, Decl(objectSpread.ts, 15, 18)) let combinedNestedChangeType: { a: number, b: boolean, c: number } = ->combinedNestedChangeType : Symbol(combinedNestedChangeType, Decl(objectSpread.ts, 25, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 25, 31)) ->b : Symbol(b, Decl(objectSpread.ts, 25, 42)) ->c : Symbol(c, Decl(objectSpread.ts, 25, 54)) +>combinedNestedChangeType : Symbol(combinedNestedChangeType, Decl(objectSpread.ts, 16, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 16, 31)) +>b : Symbol(b, Decl(objectSpread.ts, 16, 42)) +>c : Symbol(c, Decl(objectSpread.ts, 16, 54)) { ...{ a: 1, ...{ b: false, c: 'overriden' } }, c: -1 } ->a : Symbol(a, Decl(objectSpread.ts, 26, 10)) ->b : Symbol(b, Decl(objectSpread.ts, 26, 21)) ->c : Symbol(c, Decl(objectSpread.ts, 26, 31)) ->c : Symbol(c, Decl(objectSpread.ts, 26, 51)) +>a : Symbol(a, Decl(objectSpread.ts, 17, 10)) +>b : Symbol(b, Decl(objectSpread.ts, 17, 21)) +>c : Symbol(c, Decl(objectSpread.ts, 17, 31)) +>c : Symbol(c, Decl(objectSpread.ts, 17, 51)) let propertyNested: { a: { a: number, b: string } } = ->propertyNested : Symbol(propertyNested, Decl(objectSpread.ts, 27, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 27, 21)) ->a : Symbol(a, Decl(objectSpread.ts, 27, 26)) ->b : Symbol(b, Decl(objectSpread.ts, 27, 37)) +>propertyNested : Symbol(propertyNested, Decl(objectSpread.ts, 18, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 18, 21)) +>a : Symbol(a, Decl(objectSpread.ts, 18, 26)) +>b : Symbol(b, Decl(objectSpread.ts, 18, 37)) { a: { ... o } } ->a : Symbol(a, Decl(objectSpread.ts, 28, 5)) +>a : Symbol(a, Decl(objectSpread.ts, 19, 5)) >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) // accessors don't copy the descriptor // (which means that readonly getters become read/write properties) let op = { get a () { return 6 } }; ->op : Symbol(op, Decl(objectSpread.ts, 31, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 31, 10)) +>op : Symbol(op, Decl(objectSpread.ts, 22, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 22, 10)) let getter: { a: number, c: number } = ->getter : Symbol(getter, Decl(objectSpread.ts, 32, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 32, 13)) ->c : Symbol(c, Decl(objectSpread.ts, 32, 24)) +>getter : Symbol(getter, Decl(objectSpread.ts, 23, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 23, 13)) +>c : Symbol(c, Decl(objectSpread.ts, 23, 24)) { ...op, c: 7 } ->op : Symbol(op, Decl(objectSpread.ts, 31, 3)) ->c : Symbol(c, Decl(objectSpread.ts, 33, 12)) +>op : Symbol(op, Decl(objectSpread.ts, 22, 3)) +>c : Symbol(c, Decl(objectSpread.ts, 24, 12)) getter.a = 12; ->getter.a : Symbol(a, Decl(objectSpread.ts, 32, 13)) ->getter : Symbol(getter, Decl(objectSpread.ts, 32, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 32, 13)) +>getter.a : Symbol(a, Decl(objectSpread.ts, 23, 13)) +>getter : Symbol(getter, Decl(objectSpread.ts, 23, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 23, 13)) // functions result in { } let spreadFunc = { ...(function () { }) }; ->spreadFunc : Symbol(spreadFunc, Decl(objectSpread.ts, 37, 3)) +>spreadFunc : Symbol(spreadFunc, Decl(objectSpread.ts, 28, 3)) type Header = { head: string, body: string, authToken: string } ->Header : Symbol(Header, Decl(objectSpread.ts, 37, 42)) ->head : Symbol(head, Decl(objectSpread.ts, 39, 15)) ->body : Symbol(body, Decl(objectSpread.ts, 39, 29)) ->authToken : Symbol(authToken, Decl(objectSpread.ts, 39, 43)) +>Header : Symbol(Header, Decl(objectSpread.ts, 28, 42)) +>head : Symbol(head, Decl(objectSpread.ts, 30, 15)) +>body : Symbol(body, Decl(objectSpread.ts, 30, 29)) +>authToken : Symbol(authToken, Decl(objectSpread.ts, 30, 43)) function from16326(this: { header: Header }, header: Header, authToken: string): Header { ->from16326 : Symbol(from16326, Decl(objectSpread.ts, 39, 63)) ->this : Symbol(this, Decl(objectSpread.ts, 40, 19)) ->header : Symbol(header, Decl(objectSpread.ts, 40, 26)) ->Header : Symbol(Header, Decl(objectSpread.ts, 37, 42)) ->header : Symbol(header, Decl(objectSpread.ts, 40, 44)) ->Header : Symbol(Header, Decl(objectSpread.ts, 37, 42)) ->authToken : Symbol(authToken, Decl(objectSpread.ts, 40, 60)) ->Header : Symbol(Header, Decl(objectSpread.ts, 37, 42)) +>from16326 : Symbol(from16326, Decl(objectSpread.ts, 30, 63)) +>this : Symbol(this, Decl(objectSpread.ts, 31, 19)) +>header : Symbol(header, Decl(objectSpread.ts, 31, 26)) +>Header : Symbol(Header, Decl(objectSpread.ts, 28, 42)) +>header : Symbol(header, Decl(objectSpread.ts, 31, 44)) +>Header : Symbol(Header, Decl(objectSpread.ts, 28, 42)) +>authToken : Symbol(authToken, Decl(objectSpread.ts, 31, 60)) +>Header : Symbol(Header, Decl(objectSpread.ts, 28, 42)) return { ...this.header, ->this.header : Symbol(header, Decl(objectSpread.ts, 40, 26)) ->this : Symbol(this, Decl(objectSpread.ts, 40, 19)) ->header : Symbol(header, Decl(objectSpread.ts, 40, 26)) +>this.header : Symbol(header, Decl(objectSpread.ts, 31, 26)) +>this : Symbol(this, Decl(objectSpread.ts, 31, 19)) +>header : Symbol(header, Decl(objectSpread.ts, 31, 26)) ...header, ->header : Symbol(header, Decl(objectSpread.ts, 40, 44)) +>header : Symbol(header, Decl(objectSpread.ts, 31, 44)) ...authToken && { authToken } ->authToken : Symbol(authToken, Decl(objectSpread.ts, 40, 60)) ->authToken : Symbol(authToken, Decl(objectSpread.ts, 44, 25)) +>authToken : Symbol(authToken, Decl(objectSpread.ts, 31, 60)) +>authToken : Symbol(authToken, Decl(objectSpread.ts, 35, 25)) } } // boolean && T results in Partial function conditionalSpreadBoolean(b: boolean) : { x: number, y: number } { ->conditionalSpreadBoolean : Symbol(conditionalSpreadBoolean, Decl(objectSpread.ts, 46, 1)) ->b : Symbol(b, Decl(objectSpread.ts, 48, 34)) ->x : Symbol(x, Decl(objectSpread.ts, 48, 49)) ->y : Symbol(y, Decl(objectSpread.ts, 48, 60)) +>conditionalSpreadBoolean : Symbol(conditionalSpreadBoolean, Decl(objectSpread.ts, 37, 1)) +>b : Symbol(b, Decl(objectSpread.ts, 39, 34)) +>x : Symbol(x, Decl(objectSpread.ts, 39, 49)) +>y : Symbol(y, Decl(objectSpread.ts, 39, 60)) let o = { x: 12, y: 13 } ->o : Symbol(o, Decl(objectSpread.ts, 49, 7)) ->x : Symbol(x, Decl(objectSpread.ts, 49, 13)) ->y : Symbol(y, Decl(objectSpread.ts, 49, 20)) +>o : Symbol(o, Decl(objectSpread.ts, 40, 7)) +>x : Symbol(x, Decl(objectSpread.ts, 40, 13)) +>y : Symbol(y, Decl(objectSpread.ts, 40, 20)) o = { ->o : Symbol(o, Decl(objectSpread.ts, 49, 7)) +>o : Symbol(o, Decl(objectSpread.ts, 40, 7)) ...o, ->o : Symbol(o, Decl(objectSpread.ts, 49, 7)) +>o : Symbol(o, Decl(objectSpread.ts, 40, 7)) ...b && { x: 14 } ->b : Symbol(b, Decl(objectSpread.ts, 48, 34)) ->x : Symbol(x, Decl(objectSpread.ts, 52, 17)) +>b : Symbol(b, Decl(objectSpread.ts, 39, 34)) +>x : Symbol(x, Decl(objectSpread.ts, 43, 17)) } let o2 = { ...b && { x: 21 }} ->o2 : Symbol(o2, Decl(objectSpread.ts, 54, 7)) ->b : Symbol(b, Decl(objectSpread.ts, 48, 34)) ->x : Symbol(x, Decl(objectSpread.ts, 54, 24)) +>o2 : Symbol(o2, Decl(objectSpread.ts, 45, 7)) +>b : Symbol(b, Decl(objectSpread.ts, 39, 34)) +>x : Symbol(x, Decl(objectSpread.ts, 45, 24)) return o; ->o : Symbol(o, Decl(objectSpread.ts, 49, 7)) +>o : Symbol(o, Decl(objectSpread.ts, 40, 7)) } function conditionalSpreadNumber(nt: number): { x: number, y: number } { ->conditionalSpreadNumber : Symbol(conditionalSpreadNumber, Decl(objectSpread.ts, 56, 1)) ->nt : Symbol(nt, Decl(objectSpread.ts, 57, 33)) ->x : Symbol(x, Decl(objectSpread.ts, 57, 47)) ->y : Symbol(y, Decl(objectSpread.ts, 57, 58)) +>conditionalSpreadNumber : Symbol(conditionalSpreadNumber, Decl(objectSpread.ts, 47, 1)) +>nt : Symbol(nt, Decl(objectSpread.ts, 48, 33)) +>x : Symbol(x, Decl(objectSpread.ts, 48, 47)) +>y : Symbol(y, Decl(objectSpread.ts, 48, 58)) let o = { x: 15, y: 16 } ->o : Symbol(o, Decl(objectSpread.ts, 58, 7)) ->x : Symbol(x, Decl(objectSpread.ts, 58, 13)) ->y : Symbol(y, Decl(objectSpread.ts, 58, 20)) +>o : Symbol(o, Decl(objectSpread.ts, 49, 7)) +>x : Symbol(x, Decl(objectSpread.ts, 49, 13)) +>y : Symbol(y, Decl(objectSpread.ts, 49, 20)) o = { ->o : Symbol(o, Decl(objectSpread.ts, 58, 7)) +>o : Symbol(o, Decl(objectSpread.ts, 49, 7)) ...o, ->o : Symbol(o, Decl(objectSpread.ts, 58, 7)) +>o : Symbol(o, Decl(objectSpread.ts, 49, 7)) ...nt && { x: nt } ->nt : Symbol(nt, Decl(objectSpread.ts, 57, 33)) ->x : Symbol(x, Decl(objectSpread.ts, 61, 18)) ->nt : Symbol(nt, Decl(objectSpread.ts, 57, 33)) +>nt : Symbol(nt, Decl(objectSpread.ts, 48, 33)) +>x : Symbol(x, Decl(objectSpread.ts, 52, 18)) +>nt : Symbol(nt, Decl(objectSpread.ts, 48, 33)) } let o2 = { ...nt && { x: nt }} ->o2 : Symbol(o2, Decl(objectSpread.ts, 63, 7)) ->nt : Symbol(nt, Decl(objectSpread.ts, 57, 33)) ->x : Symbol(x, Decl(objectSpread.ts, 63, 25)) ->nt : Symbol(nt, Decl(objectSpread.ts, 57, 33)) +>o2 : Symbol(o2, Decl(objectSpread.ts, 54, 7)) +>nt : Symbol(nt, Decl(objectSpread.ts, 48, 33)) +>x : Symbol(x, Decl(objectSpread.ts, 54, 25)) +>nt : Symbol(nt, Decl(objectSpread.ts, 48, 33)) return o; ->o : Symbol(o, Decl(objectSpread.ts, 58, 7)) +>o : Symbol(o, Decl(objectSpread.ts, 49, 7)) } function conditionalSpreadString(st: string): { x: string, y: number } { ->conditionalSpreadString : Symbol(conditionalSpreadString, Decl(objectSpread.ts, 65, 1)) ->st : Symbol(st, Decl(objectSpread.ts, 66, 33)) ->x : Symbol(x, Decl(objectSpread.ts, 66, 47)) ->y : Symbol(y, Decl(objectSpread.ts, 66, 58)) +>conditionalSpreadString : Symbol(conditionalSpreadString, Decl(objectSpread.ts, 56, 1)) +>st : Symbol(st, Decl(objectSpread.ts, 57, 33)) +>x : Symbol(x, Decl(objectSpread.ts, 57, 47)) +>y : Symbol(y, Decl(objectSpread.ts, 57, 58)) let o = { x: 'hi', y: 17 } ->o : Symbol(o, Decl(objectSpread.ts, 67, 7)) ->x : Symbol(x, Decl(objectSpread.ts, 67, 13)) ->y : Symbol(y, Decl(objectSpread.ts, 67, 22)) +>o : Symbol(o, Decl(objectSpread.ts, 58, 7)) +>x : Symbol(x, Decl(objectSpread.ts, 58, 13)) +>y : Symbol(y, Decl(objectSpread.ts, 58, 22)) o = { ->o : Symbol(o, Decl(objectSpread.ts, 67, 7)) +>o : Symbol(o, Decl(objectSpread.ts, 58, 7)) ...o, ->o : Symbol(o, Decl(objectSpread.ts, 67, 7)) +>o : Symbol(o, Decl(objectSpread.ts, 58, 7)) ...st && { x: st } ->st : Symbol(st, Decl(objectSpread.ts, 66, 33)) ->x : Symbol(x, Decl(objectSpread.ts, 70, 18)) ->st : Symbol(st, Decl(objectSpread.ts, 66, 33)) +>st : Symbol(st, Decl(objectSpread.ts, 57, 33)) +>x : Symbol(x, Decl(objectSpread.ts, 61, 18)) +>st : Symbol(st, Decl(objectSpread.ts, 57, 33)) } let o2 = { ...st && { x: st }} ->o2 : Symbol(o2, Decl(objectSpread.ts, 72, 7)) ->st : Symbol(st, Decl(objectSpread.ts, 66, 33)) ->x : Symbol(x, Decl(objectSpread.ts, 72, 25)) ->st : Symbol(st, Decl(objectSpread.ts, 66, 33)) +>o2 : Symbol(o2, Decl(objectSpread.ts, 63, 7)) +>st : Symbol(st, Decl(objectSpread.ts, 57, 33)) +>x : Symbol(x, Decl(objectSpread.ts, 63, 25)) +>st : Symbol(st, Decl(objectSpread.ts, 57, 33)) return o; ->o : Symbol(o, Decl(objectSpread.ts, 67, 7)) +>o : Symbol(o, Decl(objectSpread.ts, 58, 7)) } // any results in any let anything: any; ->anything : Symbol(anything, Decl(objectSpread.ts, 77, 3)) +>anything : Symbol(anything, Decl(objectSpread.ts, 68, 3)) let spreadAny = { ...anything }; ->spreadAny : Symbol(spreadAny, Decl(objectSpread.ts, 78, 3)) ->anything : Symbol(anything, Decl(objectSpread.ts, 77, 3)) +>spreadAny : Symbol(spreadAny, Decl(objectSpread.ts, 69, 3)) +>anything : Symbol(anything, Decl(objectSpread.ts, 68, 3)) // methods are not enumerable class C { p = 1; m() { } } ->C : Symbol(C, Decl(objectSpread.ts, 78, 32)) ->p : Symbol(C.p, Decl(objectSpread.ts, 81, 9)) ->m : Symbol(C.m, Decl(objectSpread.ts, 81, 16)) +>C : Symbol(C, Decl(objectSpread.ts, 69, 32)) +>p : Symbol(C.p, Decl(objectSpread.ts, 72, 9)) +>m : Symbol(C.m, Decl(objectSpread.ts, 72, 16)) let c: C = new C() ->c : Symbol(c, Decl(objectSpread.ts, 82, 3)) ->C : Symbol(C, Decl(objectSpread.ts, 78, 32)) ->C : Symbol(C, Decl(objectSpread.ts, 78, 32)) +>c : Symbol(c, Decl(objectSpread.ts, 73, 3)) +>C : Symbol(C, Decl(objectSpread.ts, 69, 32)) +>C : Symbol(C, Decl(objectSpread.ts, 69, 32)) let spreadC: { p: number } = { ...c } ->spreadC : Symbol(spreadC, Decl(objectSpread.ts, 83, 3)) ->p : Symbol(p, Decl(objectSpread.ts, 83, 14)) ->c : Symbol(c, Decl(objectSpread.ts, 82, 3)) +>spreadC : Symbol(spreadC, Decl(objectSpread.ts, 74, 3)) +>p : Symbol(p, Decl(objectSpread.ts, 74, 14)) +>c : Symbol(c, Decl(objectSpread.ts, 73, 3)) // own methods are enumerable let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } }; ->cplus : Symbol(cplus, Decl(objectSpread.ts, 86, 3)) ->p : Symbol(p, Decl(objectSpread.ts, 86, 12)) ->plus : Symbol(plus, Decl(objectSpread.ts, 86, 23)) ->c : Symbol(c, Decl(objectSpread.ts, 82, 3)) ->plus : Symbol(plus, Decl(objectSpread.ts, 86, 48)) +>cplus : Symbol(cplus, Decl(objectSpread.ts, 77, 3)) +>p : Symbol(p, Decl(objectSpread.ts, 77, 12)) +>plus : Symbol(plus, Decl(objectSpread.ts, 77, 23)) +>c : Symbol(c, Decl(objectSpread.ts, 73, 3)) +>plus : Symbol(plus, Decl(objectSpread.ts, 77, 48)) cplus.plus(); ->cplus.plus : Symbol(plus, Decl(objectSpread.ts, 86, 23)) ->cplus : Symbol(cplus, Decl(objectSpread.ts, 86, 3)) ->plus : Symbol(plus, Decl(objectSpread.ts, 86, 23)) +>cplus.plus : Symbol(plus, Decl(objectSpread.ts, 77, 23)) +>cplus : Symbol(cplus, Decl(objectSpread.ts, 77, 3)) +>plus : Symbol(plus, Decl(objectSpread.ts, 77, 23)) // new field's type conflicting with existing field is OK let changeTypeAfter: { a: string, b: string } = ->changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 90, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 90, 22)) ->b : Symbol(b, Decl(objectSpread.ts, 90, 33)) +>changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 81, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 81, 22)) +>b : Symbol(b, Decl(objectSpread.ts, 81, 33)) { ...o, a: 'wrong type?' } >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 91, 11)) - -let changeTypeBefore: { a: number, b: string } = ->changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 92, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 92, 23)) ->b : Symbol(b, Decl(objectSpread.ts, 92, 34)) - - { a: 'wrong type?', ...o }; ->a : Symbol(a, Decl(objectSpread.ts, 93, 5)) ->o : Symbol(o, Decl(objectSpread.ts, 0, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 82, 11)) let changeTypeBoth: { a: string, b: number } = ->changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 94, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 94, 21)) ->b : Symbol(b, Decl(objectSpread.ts, 94, 32)) +>changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 83, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 83, 21)) +>b : Symbol(b, Decl(objectSpread.ts, 83, 32)) { ...o, ...swap }; >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) @@ -359,277 +303,263 @@ let changeTypeBoth: { a: string, b: number } = // optional function container( ->container : Symbol(container, Decl(objectSpread.ts, 95, 22)) +>container : Symbol(container, Decl(objectSpread.ts, 84, 22)) definiteBoolean: { sn: boolean }, ->definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 98, 19)) ->sn : Symbol(sn, Decl(objectSpread.ts, 99, 22)) +>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 87, 19)) +>sn : Symbol(sn, Decl(objectSpread.ts, 88, 22)) definiteString: { sn: string }, ->definiteString : Symbol(definiteString, Decl(objectSpread.ts, 99, 37)) ->sn : Symbol(sn, Decl(objectSpread.ts, 100, 21)) +>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 88, 37)) +>sn : Symbol(sn, Decl(objectSpread.ts, 89, 21)) optionalString: { sn?: string }, ->optionalString : Symbol(optionalString, Decl(objectSpread.ts, 100, 35)) ->sn : Symbol(sn, Decl(objectSpread.ts, 101, 21)) +>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 89, 35)) +>sn : Symbol(sn, Decl(objectSpread.ts, 90, 21)) optionalNumber: { sn?: number }) { ->optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 101, 36)) ->sn : Symbol(sn, Decl(objectSpread.ts, 102, 21)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 90, 36)) +>sn : Symbol(sn, Decl(objectSpread.ts, 91, 21)) let optionalUnionStops: { sn: string | number | boolean } = { ...definiteBoolean, ...definiteString, ...optionalNumber }; ->optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 103, 7)) ->sn : Symbol(sn, Decl(objectSpread.ts, 103, 29)) ->definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 98, 19)) ->definiteString : Symbol(definiteString, Decl(objectSpread.ts, 99, 37)) ->optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 101, 36)) +>optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 92, 7)) +>sn : Symbol(sn, Decl(objectSpread.ts, 92, 29)) +>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 87, 19)) +>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 88, 37)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 90, 36)) let optionalUnionDuplicates: { sn: string | number } = { ...definiteBoolean, ...definiteString, ...optionalString, ...optionalNumber }; ->optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 104, 7)) ->sn : Symbol(sn, Decl(objectSpread.ts, 104, 34)) ->definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 98, 19)) ->definiteString : Symbol(definiteString, Decl(objectSpread.ts, 99, 37)) ->optionalString : Symbol(optionalString, Decl(objectSpread.ts, 100, 35)) ->optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 101, 36)) +>optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 93, 7)) +>sn : Symbol(sn, Decl(objectSpread.ts, 93, 34)) +>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 87, 19)) +>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 88, 37)) +>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 89, 35)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 90, 36)) let allOptional: { sn?: string | number } = { ...optionalString, ...optionalNumber }; ->allOptional : Symbol(allOptional, Decl(objectSpread.ts, 105, 7)) ->sn : Symbol(sn, Decl(objectSpread.ts, 105, 22)) ->optionalString : Symbol(optionalString, Decl(objectSpread.ts, 100, 35)) ->optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 101, 36)) +>allOptional : Symbol(allOptional, Decl(objectSpread.ts, 94, 7)) +>sn : Symbol(sn, Decl(objectSpread.ts, 94, 22)) +>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 89, 35)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 90, 36)) // computed property let computedFirst: { a: number, b: string, "before everything": number } = ->computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 108, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 108, 24)) ->b : Symbol(b, Decl(objectSpread.ts, 108, 35)) ->"before everything" : Symbol("before everything", Decl(objectSpread.ts, 108, 46)) +>computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 97, 7)) +>a : Symbol(a, Decl(objectSpread.ts, 97, 24)) +>b : Symbol(b, Decl(objectSpread.ts, 97, 35)) +>"before everything" : Symbol("before everything", Decl(objectSpread.ts, 97, 46)) { ['before everything']: 12, ...o, b: 'yes' } ->['before everything'] : Symbol(['before everything'], Decl(objectSpread.ts, 109, 9)) ->'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 109, 9)) ->o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->b : Symbol(b, Decl(objectSpread.ts, 109, 42)) - - let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = ->computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 110, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 110, 25)) ->b : Symbol(b, Decl(objectSpread.ts, 110, 36)) ->c : Symbol(c, Decl(objectSpread.ts, 110, 47)) ->"in the middle" : Symbol("in the middle", Decl(objectSpread.ts, 110, 59)) - - { ...o, ['in the middle']: 13, b: 'maybe?', ...o2 } +>['before everything'] : Symbol(['before everything'], Decl(objectSpread.ts, 98, 9)) +>'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 98, 9)) >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->['in the middle'] : Symbol(['in the middle'], Decl(objectSpread.ts, 111, 15)) ->'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 111, 15)) ->b : Symbol(b, Decl(objectSpread.ts, 111, 38)) ->o2 : Symbol(o2, Decl(objectSpread.ts, 1, 3)) +>b : Symbol(b, Decl(objectSpread.ts, 98, 42)) let computedAfter: { a: number, b: string, "at the end": number } = ->computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 112, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 112, 24)) ->b : Symbol(b, Decl(objectSpread.ts, 112, 35)) ->"at the end" : Symbol("at the end", Decl(objectSpread.ts, 112, 46)) +>computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 99, 7)) +>a : Symbol(a, Decl(objectSpread.ts, 99, 24)) +>b : Symbol(b, Decl(objectSpread.ts, 99, 35)) +>"at the end" : Symbol("at the end", Decl(objectSpread.ts, 99, 46)) { ...o, b: 'yeah', ['at the end']: 14 } >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->b : Symbol(b, Decl(objectSpread.ts, 113, 15)) ->['at the end'] : Symbol(['at the end'], Decl(objectSpread.ts, 113, 26)) ->'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 113, 26)) +>b : Symbol(b, Decl(objectSpread.ts, 100, 15)) +>['at the end'] : Symbol(['at the end'], Decl(objectSpread.ts, 100, 26)) +>'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 100, 26)) } // shortcut syntax let a = 12; ->a : Symbol(a, Decl(objectSpread.ts, 116, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 103, 3)) let shortCutted: { a: number, b: string } = { ...o, a } ->shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 117, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 117, 18)) ->b : Symbol(b, Decl(objectSpread.ts, 117, 29)) +>shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 104, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 104, 18)) +>b : Symbol(b, Decl(objectSpread.ts, 104, 29)) >o : Symbol(o, Decl(objectSpread.ts, 0, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 117, 51)) +>a : Symbol(a, Decl(objectSpread.ts, 104, 51)) // non primitive let spreadNonPrimitive = { ...{}}; ->spreadNonPrimitive : Symbol(spreadNonPrimitive, Decl(objectSpread.ts, 119, 3)) +>spreadNonPrimitive : Symbol(spreadNonPrimitive, Decl(objectSpread.ts, 106, 3)) // generic spreads function f(t: T, u: U) { ->f : Symbol(f, Decl(objectSpread.ts, 119, 42)) ->T : Symbol(T, Decl(objectSpread.ts, 123, 11)) ->U : Symbol(U, Decl(objectSpread.ts, 123, 13)) ->t : Symbol(t, Decl(objectSpread.ts, 123, 17)) ->T : Symbol(T, Decl(objectSpread.ts, 123, 11)) ->u : Symbol(u, Decl(objectSpread.ts, 123, 22)) ->U : Symbol(U, Decl(objectSpread.ts, 123, 13)) +>f : Symbol(f, Decl(objectSpread.ts, 106, 42)) +>T : Symbol(T, Decl(objectSpread.ts, 110, 11)) +>U : Symbol(U, Decl(objectSpread.ts, 110, 13)) +>t : Symbol(t, Decl(objectSpread.ts, 110, 17)) +>T : Symbol(T, Decl(objectSpread.ts, 110, 11)) +>u : Symbol(u, Decl(objectSpread.ts, 110, 22)) +>U : Symbol(U, Decl(objectSpread.ts, 110, 13)) return { ...t, ...u, id: 'id' }; ->t : Symbol(t, Decl(objectSpread.ts, 123, 17)) ->u : Symbol(u, Decl(objectSpread.ts, 123, 22)) ->id : Symbol(id, Decl(objectSpread.ts, 124, 24)) +>t : Symbol(t, Decl(objectSpread.ts, 110, 17)) +>u : Symbol(u, Decl(objectSpread.ts, 110, 22)) +>id : Symbol(id, Decl(objectSpread.ts, 111, 24)) } let exclusive: { id: string, a: number, b: string, c: string, d: boolean } = ->exclusive : Symbol(exclusive, Decl(objectSpread.ts, 127, 3)) ->id : Symbol(id, Decl(objectSpread.ts, 127, 16)) ->a : Symbol(a, Decl(objectSpread.ts, 127, 28)) ->b : Symbol(b, Decl(objectSpread.ts, 127, 39)) ->c : Symbol(c, Decl(objectSpread.ts, 127, 50)) ->d : Symbol(d, Decl(objectSpread.ts, 127, 61)) +>exclusive : Symbol(exclusive, Decl(objectSpread.ts, 114, 3)) +>id : Symbol(id, Decl(objectSpread.ts, 114, 16)) +>a : Symbol(a, Decl(objectSpread.ts, 114, 28)) +>b : Symbol(b, Decl(objectSpread.ts, 114, 39)) +>c : Symbol(c, Decl(objectSpread.ts, 114, 50)) +>d : Symbol(d, Decl(objectSpread.ts, 114, 61)) f({ a: 1, b: 'yes' }, { c: 'no', d: false }) ->f : Symbol(f, Decl(objectSpread.ts, 119, 42)) ->a : Symbol(a, Decl(objectSpread.ts, 128, 7)) ->b : Symbol(b, Decl(objectSpread.ts, 128, 13)) ->c : Symbol(c, Decl(objectSpread.ts, 128, 27)) ->d : Symbol(d, Decl(objectSpread.ts, 128, 36)) +>f : Symbol(f, Decl(objectSpread.ts, 106, 42)) +>a : Symbol(a, Decl(objectSpread.ts, 115, 7)) +>b : Symbol(b, Decl(objectSpread.ts, 115, 13)) +>c : Symbol(c, Decl(objectSpread.ts, 115, 27)) +>d : Symbol(d, Decl(objectSpread.ts, 115, 36)) let overlap: { id: string, a: number, b: string } = ->overlap : Symbol(overlap, Decl(objectSpread.ts, 129, 3)) ->id : Symbol(id, Decl(objectSpread.ts, 129, 14)) ->a : Symbol(a, Decl(objectSpread.ts, 129, 26)) ->b : Symbol(b, Decl(objectSpread.ts, 129, 37)) +>overlap : Symbol(overlap, Decl(objectSpread.ts, 116, 3)) +>id : Symbol(id, Decl(objectSpread.ts, 116, 14)) +>a : Symbol(a, Decl(objectSpread.ts, 116, 26)) +>b : Symbol(b, Decl(objectSpread.ts, 116, 37)) f({ a: 1 }, { a: 2, b: 'extra' }) ->f : Symbol(f, Decl(objectSpread.ts, 119, 42)) ->a : Symbol(a, Decl(objectSpread.ts, 130, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 130, 17)) ->b : Symbol(b, Decl(objectSpread.ts, 130, 23)) +>f : Symbol(f, Decl(objectSpread.ts, 106, 42)) +>a : Symbol(a, Decl(objectSpread.ts, 117, 7)) +>a : Symbol(a, Decl(objectSpread.ts, 117, 17)) +>b : Symbol(b, Decl(objectSpread.ts, 117, 23)) let overlapConflict: { id:string, a: string } = ->overlapConflict : Symbol(overlapConflict, Decl(objectSpread.ts, 131, 3)) ->id : Symbol(id, Decl(objectSpread.ts, 131, 22)) ->a : Symbol(a, Decl(objectSpread.ts, 131, 33)) +>overlapConflict : Symbol(overlapConflict, Decl(objectSpread.ts, 118, 3)) +>id : Symbol(id, Decl(objectSpread.ts, 118, 22)) +>a : Symbol(a, Decl(objectSpread.ts, 118, 33)) f({ a: 1 }, { a: 'mismatch' }) ->f : Symbol(f, Decl(objectSpread.ts, 119, 42)) ->a : Symbol(a, Decl(objectSpread.ts, 132, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 132, 17)) +>f : Symbol(f, Decl(objectSpread.ts, 106, 42)) +>a : Symbol(a, Decl(objectSpread.ts, 119, 7)) +>a : Symbol(a, Decl(objectSpread.ts, 119, 17)) let overwriteId: { id: string, a: number, c: number, d: string } = ->overwriteId : Symbol(overwriteId, Decl(objectSpread.ts, 133, 3)) ->id : Symbol(id, Decl(objectSpread.ts, 133, 18)) ->a : Symbol(a, Decl(objectSpread.ts, 133, 30)) ->c : Symbol(c, Decl(objectSpread.ts, 133, 41)) ->d : Symbol(d, Decl(objectSpread.ts, 133, 52)) +>overwriteId : Symbol(overwriteId, Decl(objectSpread.ts, 120, 3)) +>id : Symbol(id, Decl(objectSpread.ts, 120, 18)) +>a : Symbol(a, Decl(objectSpread.ts, 120, 30)) +>c : Symbol(c, Decl(objectSpread.ts, 120, 41)) +>d : Symbol(d, Decl(objectSpread.ts, 120, 52)) f({ a: 1, id: true }, { c: 1, d: 'no' }) ->f : Symbol(f, Decl(objectSpread.ts, 119, 42)) ->a : Symbol(a, Decl(objectSpread.ts, 134, 7)) ->id : Symbol(id, Decl(objectSpread.ts, 134, 13)) ->c : Symbol(c, Decl(objectSpread.ts, 134, 27)) ->d : Symbol(d, Decl(objectSpread.ts, 134, 33)) +>f : Symbol(f, Decl(objectSpread.ts, 106, 42)) +>a : Symbol(a, Decl(objectSpread.ts, 121, 7)) +>id : Symbol(id, Decl(objectSpread.ts, 121, 13)) +>c : Symbol(c, Decl(objectSpread.ts, 121, 27)) +>d : Symbol(d, Decl(objectSpread.ts, 121, 33)) function genericSpread(t: T, u: U, v: T | U, w: T | { s: string }, obj: { x: number }) { ->genericSpread : Symbol(genericSpread, Decl(objectSpread.ts, 134, 44)) ->T : Symbol(T, Decl(objectSpread.ts, 136, 23)) ->U : Symbol(U, Decl(objectSpread.ts, 136, 25)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->T : Symbol(T, Decl(objectSpread.ts, 136, 23)) ->u : Symbol(u, Decl(objectSpread.ts, 136, 34)) ->U : Symbol(U, Decl(objectSpread.ts, 136, 25)) ->v : Symbol(v, Decl(objectSpread.ts, 136, 40)) ->T : Symbol(T, Decl(objectSpread.ts, 136, 23)) ->U : Symbol(U, Decl(objectSpread.ts, 136, 25)) ->w : Symbol(w, Decl(objectSpread.ts, 136, 50)) ->T : Symbol(T, Decl(objectSpread.ts, 136, 23)) ->s : Symbol(s, Decl(objectSpread.ts, 136, 59)) ->obj : Symbol(obj, Decl(objectSpread.ts, 136, 72)) ->x : Symbol(x, Decl(objectSpread.ts, 136, 79)) +>genericSpread : Symbol(genericSpread, Decl(objectSpread.ts, 121, 44)) +>T : Symbol(T, Decl(objectSpread.ts, 123, 23)) +>U : Symbol(U, Decl(objectSpread.ts, 123, 25)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>T : Symbol(T, Decl(objectSpread.ts, 123, 23)) +>u : Symbol(u, Decl(objectSpread.ts, 123, 34)) +>U : Symbol(U, Decl(objectSpread.ts, 123, 25)) +>v : Symbol(v, Decl(objectSpread.ts, 123, 40)) +>T : Symbol(T, Decl(objectSpread.ts, 123, 23)) +>U : Symbol(U, Decl(objectSpread.ts, 123, 25)) +>w : Symbol(w, Decl(objectSpread.ts, 123, 50)) +>T : Symbol(T, Decl(objectSpread.ts, 123, 23)) +>s : Symbol(s, Decl(objectSpread.ts, 123, 59)) +>obj : Symbol(obj, Decl(objectSpread.ts, 123, 72)) +>x : Symbol(x, Decl(objectSpread.ts, 123, 79)) let x01 = { ...t }; ->x01 : Symbol(x01, Decl(objectSpread.ts, 137, 7)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) +>x01 : Symbol(x01, Decl(objectSpread.ts, 124, 7)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) let x02 = { ...t, ...t }; ->x02 : Symbol(x02, Decl(objectSpread.ts, 138, 7)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) +>x02 : Symbol(x02, Decl(objectSpread.ts, 125, 7)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) let x03 = { ...t, ...u }; ->x03 : Symbol(x03, Decl(objectSpread.ts, 139, 7)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->u : Symbol(u, Decl(objectSpread.ts, 136, 34)) +>x03 : Symbol(x03, Decl(objectSpread.ts, 126, 7)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>u : Symbol(u, Decl(objectSpread.ts, 123, 34)) let x04 = { ...u, ...t }; ->x04 : Symbol(x04, Decl(objectSpread.ts, 140, 7)) ->u : Symbol(u, Decl(objectSpread.ts, 136, 34)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) +>x04 : Symbol(x04, Decl(objectSpread.ts, 127, 7)) +>u : Symbol(u, Decl(objectSpread.ts, 123, 34)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) let x05 = { a: 5, b: 'hi', ...t }; ->x05 : Symbol(x05, Decl(objectSpread.ts, 141, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 141, 15)) ->b : Symbol(b, Decl(objectSpread.ts, 141, 21)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) +>x05 : Symbol(x05, Decl(objectSpread.ts, 128, 7)) +>a : Symbol(a, Decl(objectSpread.ts, 128, 15)) +>b : Symbol(b, Decl(objectSpread.ts, 128, 21)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) let x06 = { ...t, a: 5, b: 'hi' }; ->x06 : Symbol(x06, Decl(objectSpread.ts, 142, 7)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->a : Symbol(a, Decl(objectSpread.ts, 142, 21)) ->b : Symbol(b, Decl(objectSpread.ts, 142, 27)) +>x06 : Symbol(x06, Decl(objectSpread.ts, 129, 7)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>a : Symbol(a, Decl(objectSpread.ts, 129, 21)) +>b : Symbol(b, Decl(objectSpread.ts, 129, 27)) let x07 = { a: 5, b: 'hi', ...t, c: true, ...obj }; ->x07 : Symbol(x07, Decl(objectSpread.ts, 143, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 143, 15)) ->b : Symbol(b, Decl(objectSpread.ts, 143, 21)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->c : Symbol(c, Decl(objectSpread.ts, 143, 36)) ->obj : Symbol(obj, Decl(objectSpread.ts, 136, 72)) +>x07 : Symbol(x07, Decl(objectSpread.ts, 130, 7)) +>a : Symbol(a, Decl(objectSpread.ts, 130, 15)) +>b : Symbol(b, Decl(objectSpread.ts, 130, 21)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>c : Symbol(c, Decl(objectSpread.ts, 130, 36)) +>obj : Symbol(obj, Decl(objectSpread.ts, 123, 72)) let x09 = { a: 5, ...t, b: 'hi', c: true, ...obj }; ->x09 : Symbol(x09, Decl(objectSpread.ts, 144, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 144, 15)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->b : Symbol(b, Decl(objectSpread.ts, 144, 27)) ->c : Symbol(c, Decl(objectSpread.ts, 144, 36)) ->obj : Symbol(obj, Decl(objectSpread.ts, 136, 72)) +>x09 : Symbol(x09, Decl(objectSpread.ts, 131, 7)) +>a : Symbol(a, Decl(objectSpread.ts, 131, 15)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>b : Symbol(b, Decl(objectSpread.ts, 131, 27)) +>c : Symbol(c, Decl(objectSpread.ts, 131, 36)) +>obj : Symbol(obj, Decl(objectSpread.ts, 123, 72)) let x10 = { a: 5, ...t, b: 'hi', ...u, ...obj }; ->x10 : Symbol(x10, Decl(objectSpread.ts, 145, 7)) ->a : Symbol(a, Decl(objectSpread.ts, 145, 15)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->b : Symbol(b, Decl(objectSpread.ts, 145, 27)) ->u : Symbol(u, Decl(objectSpread.ts, 136, 34)) ->obj : Symbol(obj, Decl(objectSpread.ts, 136, 72)) +>x10 : Symbol(x10, Decl(objectSpread.ts, 132, 7)) +>a : Symbol(a, Decl(objectSpread.ts, 132, 15)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>b : Symbol(b, Decl(objectSpread.ts, 132, 27)) +>u : Symbol(u, Decl(objectSpread.ts, 123, 34)) +>obj : Symbol(obj, Decl(objectSpread.ts, 123, 72)) let x11 = { ...v }; ->x11 : Symbol(x11, Decl(objectSpread.ts, 146, 7)) ->v : Symbol(v, Decl(objectSpread.ts, 136, 40)) +>x11 : Symbol(x11, Decl(objectSpread.ts, 133, 7)) +>v : Symbol(v, Decl(objectSpread.ts, 123, 40)) let x12 = { ...v, ...obj }; ->x12 : Symbol(x12, Decl(objectSpread.ts, 147, 7)) ->v : Symbol(v, Decl(objectSpread.ts, 136, 40)) ->obj : Symbol(obj, Decl(objectSpread.ts, 136, 72)) +>x12 : Symbol(x12, Decl(objectSpread.ts, 134, 7)) +>v : Symbol(v, Decl(objectSpread.ts, 123, 40)) +>obj : Symbol(obj, Decl(objectSpread.ts, 123, 72)) let x13 = { ...w }; ->x13 : Symbol(x13, Decl(objectSpread.ts, 148, 7)) ->w : Symbol(w, Decl(objectSpread.ts, 136, 50)) +>x13 : Symbol(x13, Decl(objectSpread.ts, 135, 7)) +>w : Symbol(w, Decl(objectSpread.ts, 123, 50)) let x14 = { ...w, ...obj }; ->x14 : Symbol(x14, Decl(objectSpread.ts, 149, 7)) ->w : Symbol(w, Decl(objectSpread.ts, 136, 50)) ->obj : Symbol(obj, Decl(objectSpread.ts, 136, 72)) +>x14 : Symbol(x14, Decl(objectSpread.ts, 136, 7)) +>w : Symbol(w, Decl(objectSpread.ts, 123, 50)) +>obj : Symbol(obj, Decl(objectSpread.ts, 123, 72)) let x15 = { ...t, ...v }; ->x15 : Symbol(x15, Decl(objectSpread.ts, 150, 7)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->v : Symbol(v, Decl(objectSpread.ts, 136, 40)) +>x15 : Symbol(x15, Decl(objectSpread.ts, 137, 7)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>v : Symbol(v, Decl(objectSpread.ts, 123, 40)) let x16 = { ...t, ...w }; ->x16 : Symbol(x16, Decl(objectSpread.ts, 151, 7)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->w : Symbol(w, Decl(objectSpread.ts, 136, 50)) +>x16 : Symbol(x16, Decl(objectSpread.ts, 138, 7)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>w : Symbol(w, Decl(objectSpread.ts, 123, 50)) let x17 = { ...t, ...w, ...obj }; ->x17 : Symbol(x17, Decl(objectSpread.ts, 152, 7)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->w : Symbol(w, Decl(objectSpread.ts, 136, 50)) ->obj : Symbol(obj, Decl(objectSpread.ts, 136, 72)) +>x17 : Symbol(x17, Decl(objectSpread.ts, 139, 7)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>w : Symbol(w, Decl(objectSpread.ts, 123, 50)) +>obj : Symbol(obj, Decl(objectSpread.ts, 123, 72)) let x18 = { ...t, ...v, ...w }; ->x18 : Symbol(x18, Decl(objectSpread.ts, 153, 7)) ->t : Symbol(t, Decl(objectSpread.ts, 136, 29)) ->v : Symbol(v, Decl(objectSpread.ts, 136, 40)) ->w : Symbol(w, Decl(objectSpread.ts, 136, 50)) +>x18 : Symbol(x18, Decl(objectSpread.ts, 140, 7)) +>t : Symbol(t, Decl(objectSpread.ts, 123, 29)) +>v : Symbol(v, Decl(objectSpread.ts, 123, 40)) +>w : Symbol(w, Decl(objectSpread.ts, 123, 50)) } diff --git a/tests/baselines/reference/objectSpread.types b/tests/baselines/reference/objectSpread.types index 2154a8ca75e71..5b0da12ed906a 100644 --- a/tests/baselines/reference/objectSpread.types +++ b/tests/baselines/reference/objectSpread.types @@ -48,18 +48,6 @@ let addBefore: { a: number, b: string, c: boolean } = >false : false >o : { a: number; b: string; } -// Note: ignore still changes the order that properties are printed -let ignore: { a: number, b: string } = ->ignore : { a: number; b: string; } ->a : number ->b : string - - { b: 'ignored', ...o } ->{ b: 'ignored', ...o } : { a: number; b: string; } ->b : string ->'ignored' : "ignored" ->o : { a: number; b: string; } - let override: { a: number, b: string } = >override : { a: number; b: string; } >a : number @@ -101,32 +89,6 @@ let combined: { a: number, b: string, c: boolean } = >o : { a: number; b: string; } >o2 : { b: string; c: boolean; } -let combinedBefore: { a: number, b: string, c: boolean } = ->combinedBefore : { a: number; b: string; c: boolean; } ->a : number ->b : string ->c : boolean - - { b: 'ok', ...o, ...o2 } ->{ b: 'ok', ...o, ...o2 } : { b: string; c: boolean; a: number; } ->b : string ->'ok' : "ok" ->o : { a: number; b: string; } ->o2 : { b: string; c: boolean; } - -let combinedMid: { a: number, b: string, c: boolean } = ->combinedMid : { a: number; b: string; c: boolean; } ->a : number ->b : string ->c : boolean - - { ...o, b: 'ok', ...o2 } ->{ ...o, b: 'ok', ...o2 } : { b: string; c: boolean; a: number; } ->o : { a: number; b: string; } ->b : string ->'ok' : "ok" ->o2 : { b: string; c: boolean; } - let combinedAfter: { a: number, b: string, c: boolean } = >combinedAfter : { a: number; b: string; c: boolean; } >a : number @@ -140,31 +102,6 @@ let combinedAfter: { a: number, b: string, c: boolean } = >b : string >'ok' : "ok" -let combinedNested: { a: number, b: boolean, c: string, d: string } = ->combinedNested : { a: number; b: boolean; c: string; d: string; } ->a : number ->b : boolean ->c : string ->d : string - - { ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } ->{ ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } : { a: number; d: string; b: false; c: string; } ->{ a: 4, ...{ b: false, c: 'overriden' } } : { b: false; c: string; a: number; } ->a : number ->4 : 4 ->{ b: false, c: 'overriden' } : { b: false; c: string; } ->b : false ->false : false ->c : string ->'overriden' : "overriden" ->d : string ->'actually new' : "actually new" ->{ a: 5, d: 'maybe new' } : { a: number; d: string; } ->a : number ->5 : 5 ->d : string ->'maybe new' : "maybe new" - let combinedNestedChangeType: { a: number, b: boolean, c: number } = >combinedNestedChangeType : { a: number; b: boolean; c: number; } >a : number @@ -445,17 +382,6 @@ let changeTypeAfter: { a: string, b: string } = >a : string >'wrong type?' : "wrong type?" -let changeTypeBefore: { a: number, b: string } = ->changeTypeBefore : { a: number; b: string; } ->a : number ->b : string - - { a: 'wrong type?', ...o }; ->{ a: 'wrong type?', ...o } : { a: number; b: string; } ->a : string ->'wrong type?' : "wrong type?" ->o : { a: number; b: string; } - let changeTypeBoth: { a: string, b: number } = >changeTypeBoth : { a: string; b: number; } >a : string @@ -526,23 +452,6 @@ function container( >b : string >'yes' : "yes" - let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = ->computedMiddle : { a: number; b: string; c: boolean; "in the middle": number; } ->a : number ->b : string ->c : boolean ->"in the middle" : number - - { ...o, ['in the middle']: 13, b: 'maybe?', ...o2 } ->{ ...o, ['in the middle']: 13, b: 'maybe?', ...o2 } : { b: string; c: boolean; "in the middle": number; a: number; } ->o : { a: number; b: string; } ->['in the middle'] : number ->'in the middle' : "in the middle" ->13 : 13 ->b : string ->'maybe?' : "maybe?" ->o2 : { b: string; c: boolean; } - let computedAfter: { a: number, b: string, "at the end": number } = >computedAfter : { a: number; b: string; "at the end": number; } >a : number diff --git a/tests/baselines/reference/objectSpreadNegative.errors.txt b/tests/baselines/reference/objectSpreadNegative.errors.txt index 914df6d78d883..8b0ae9abbc515 100644 --- a/tests/baselines/reference/objectSpreadNegative.errors.txt +++ b/tests/baselines/reference/objectSpreadNegative.errors.txt @@ -1,23 +1,32 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(13,21): error TS2339: Property 'x' does not exist on type '{}'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(16,5): error TS2322: Type '{ sn?: string | number; }' is not assignable to type '{ sn: string | number; }'. - Property 'sn' is optional in type '{ sn?: string | number; }' but required in type '{ sn: string | number; }'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(16,5): error TS2322: Type '{ sn?: string | number | undefined; }' is not assignable to type '{ sn: string | number; }'. + Types of property 'sn' are incompatible. + Type 'string | number | undefined' is not assignable to type 'string | number'. + Type 'undefined' is not assignable to type 'string | number'. tests/cases/conformance/types/spread/objectSpreadNegative.ts(23,1): error TS2741: Property 'b' is missing in type '{ s: string; }' but required in type '{ s: string; b: boolean; }'. tests/cases/conformance/types/spread/objectSpreadNegative.ts(25,1): error TS2741: Property 's' is missing in type '{ b: boolean; }' but required in type '{ s: string; b: boolean; }'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(28,20): error TS2783: 'b' is specified more than once, so this usage will be overwritten. 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(34,20): error TS2698: Spread types may only be created from object types. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(36,20): error TS2698: Spread types may only be created from object types. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(38,19): error TS2698: Spread types may only be created from object types. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(43,1): error TS2349: This expression is not callable. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(32,7): error TS2783: 'b' is specified more than once, so this usage will be overwritten. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(37,7): error TS2783: 'b' is specified more than once, so this usage will be overwritten. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(39,14): error TS2783: 'b' is specified more than once, so this usage will be overwritten. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(41,53): error TS2783: 'd' is specified more than once, so this usage will be overwritten. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(43,7): error TS2783: 'a' is specified more than once, so this usage will be overwritten. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(45,37): error TS2783: 'b' is specified more than once, so this usage will be overwritten. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(48,19): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(49,19): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(50,20): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(52,20): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(54,19): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(59,1): error TS2349: This expression is not callable. Type '{}' has no call signatures. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(47,1): error TS2322: Type '12' is not assignable to type 'undefined'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(53,9): error TS2339: Property 'm' does not exist on type '{ p: number; }'. -tests/cases/conformance/types/spread/objectSpreadNegative.ts(58,11): error TS2339: Property 'a' does not exist on type '{}'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(63,1): error TS2322: Type '12' is not assignable to type 'undefined'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(69,9): error TS2339: Property 'm' does not exist on type '{ p: number; }'. +tests/cases/conformance/types/spread/objectSpreadNegative.ts(74,11): error TS2339: Property 'a' does not exist on type '{}'. -==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (15 errors) ==== +==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (22 errors) ==== let o = { a: 1, b: 'no' } /// private propagates @@ -27,18 +36,20 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(58,11): error TS233 class PublicX { public x: number; } - let publicX: PublicX; - let privateOptionalX: PrivateOptionalX; + declare let publicX: PublicX; + declare let privateOptionalX: PrivateOptionalX; let o2 = { ...publicX, ...privateOptionalX }; let sn: number = o2.x; // error, x is private ~ !!! error TS2339: Property 'x' does not exist on type '{}'. - let optionalString: { sn?: string }; - let optionalNumber: { sn?: number }; + declare let optionalString: { sn?: string }; + declare let optionalNumber: { sn?: number }; let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumber }; ~~~~~~~~~~~ -!!! error TS2322: Type '{ sn?: string | number; }' is not assignable to type '{ sn: string | number; }'. -!!! error TS2322: Property 'sn' is optional in type '{ sn?: string | number; }' but required in type '{ sn: string | number; }'. +!!! error TS2322: Type '{ sn?: string | number | undefined; }' is not assignable to type '{ sn: string | number; }'. +!!! error TS2322: Types of property 'sn' are incompatible. +!!! error TS2322: Type 'string | number | undefined' is not assignable to type 'string | number'. +!!! error TS2322: Type 'undefined' is not assignable to type 'string | number'. // error, 'sn' is optional in source, required in target // assignability as target @@ -57,11 +68,41 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(58,11): error TS233 // literal repeats are not allowed, but spread repeats are fine let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' } + ~~~~~~~~ +!!! error TS2783: 'b' is specified more than once, so this usage will be overwritten. ~ !!! error TS2300: Duplicate identifier 'b'. ~ !!! error TS2300: Duplicate identifier 'b'. let duplicatedSpread = { ...o, ...o } + // Note: ignore changes the order that properties are printed + let ignore: { a: number, b: string } = + { b: 'ignored', ...o } + ~~~~~~~~~~~~ +!!! error TS2783: 'b' is specified more than once, so this usage will be overwritten. + + let o3 = { a: 1, b: 'no' } + let o4 = { b: 'yes', c: true } + let combinedBefore: { a: number, b: string, c: boolean } = + { b: 'ok', ...o3, ...o4 } + ~~~~~~~ +!!! error TS2783: 'b' is specified more than once, so this usage will be overwritten. + let combinedMid: { a: number, b: string, c: boolean } = + { ...o3, b: 'ok', ...o4 } + ~~~~~~~ +!!! error TS2783: 'b' is specified more than once, so this usage will be overwritten. + let combinedNested: { a: number, b: boolean, c: string, d: string } = + { ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } + ~~~~~~~~~~~~~~~~~ +!!! error TS2783: 'd' is specified more than once, so this usage will be overwritten. + let changeTypeBefore: { a: number, b: string } = + { a: 'wrong type?', ...o3 }; + ~~~~~~~~~~~~~~~~ +!!! error TS2783: 'a' is specified more than once, so this usage will be overwritten. + let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = + { ...o3, ['in the middle']: 13, b: 'maybe?', ...o4 } + ~~~~~~~~~~~ +!!! error TS2783: 'b' is specified more than once, so this usage will be overwritten. // primitives are not allowed, except for falsy ones let spreadNum = { ...12 }; diff --git a/tests/baselines/reference/objectSpreadNegative.js b/tests/baselines/reference/objectSpreadNegative.js index 6151f2d30b7c4..444f979a89541 100644 --- a/tests/baselines/reference/objectSpreadNegative.js +++ b/tests/baselines/reference/objectSpreadNegative.js @@ -8,12 +8,12 @@ class PrivateOptionalX { class PublicX { public x: number; } -let publicX: PublicX; -let privateOptionalX: PrivateOptionalX; +declare let publicX: PublicX; +declare let privateOptionalX: PrivateOptionalX; let o2 = { ...publicX, ...privateOptionalX }; let sn: number = o2.x; // error, x is private -let optionalString: { sn?: string }; -let optionalNumber: { sn?: number }; +declare let optionalString: { sn?: string }; +declare let optionalNumber: { sn?: number }; let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumber }; // error, 'sn' is optional in source, required in target @@ -28,6 +28,22 @@ 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 } +// Note: ignore changes the order that properties are printed +let ignore: { a: number, b: string } = + { b: 'ignored', ...o } + +let o3 = { a: 1, b: 'no' } +let o4 = { b: 'yes', c: true } +let combinedBefore: { a: number, b: string, c: boolean } = + { b: 'ok', ...o3, ...o4 } +let combinedMid: { a: number, b: string, c: boolean } = + { ...o3, b: 'ok', ...o4 } +let combinedNested: { a: number, b: boolean, c: string, d: string } = + { ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } +let changeTypeBefore: { a: number, b: string } = + { a: 'wrong type?', ...o3 }; +let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = + { ...o3, ['in the middle']: 13, b: 'maybe?', ...o4 } // primitives are not allowed, except for falsy ones let spreadNum = { ...12 }; @@ -71,6 +87,7 @@ var __assign = (this && this.__assign) || function () { }; return __assign.apply(this, arguments); }; +var _a; var o = { a: 1, b: 'no' }; /// private propagates var PrivateOptionalX = /** @class */ (function () { @@ -83,12 +100,8 @@ var PublicX = /** @class */ (function () { } return PublicX; }()); -var publicX; -var privateOptionalX; var o2 = __assign(__assign({}, publicX), privateOptionalX); var sn = o2.x; // error, x is private -var optionalString; -var optionalNumber; var allOptional = __assign(__assign({}, optionalString), optionalNumber); ; ; @@ -99,6 +112,15 @@ spread = b; // error, missing 's' // literal repeats are not allowed, but spread repeats are fine var duplicated = __assign(__assign(__assign(__assign({ b: 'bad' }, o), { b: 'bad' }), o2), { b: 'bad' }); var duplicatedSpread = __assign(__assign({}, o), o); +// Note: ignore changes the order that properties are printed +var ignore = __assign({ b: 'ignored' }, o); +var o3 = { a: 1, b: 'no' }; +var o4 = { b: 'yes', c: true }; +var combinedBefore = __assign(__assign({ b: 'ok' }, o3), o4); +var combinedMid = __assign(__assign(__assign({}, o3), { b: 'ok' }), o4); +var combinedNested = __assign(__assign(__assign({}, __assign({ a: 4 }, { b: false, c: 'overriden' })), { d: 'actually new' }), { a: 5, d: 'maybe new' }); +var changeTypeBefore = __assign({ a: 'wrong type?' }, o3); +var computedMiddle = __assign(__assign(__assign({}, o3), (_a = {}, _a['in the middle'] = 13, _a.b = 'maybe?', _a)), o4); // primitives are not allowed, except for falsy ones var spreadNum = __assign({}, 12); var spreadSum = __assign({}, 1 + 1); diff --git a/tests/baselines/reference/objectSpreadNegative.symbols b/tests/baselines/reference/objectSpreadNegative.symbols index 4962630cebdd7..3ce3dff9b2fe9 100644 --- a/tests/baselines/reference/objectSpreadNegative.symbols +++ b/tests/baselines/reference/objectSpreadNegative.symbols @@ -17,36 +17,36 @@ class PublicX { public x: number; >x : Symbol(PublicX.x, Decl(objectSpreadNegative.ts, 6, 15)) } -let publicX: PublicX; ->publicX : Symbol(publicX, Decl(objectSpreadNegative.ts, 9, 3)) +declare let publicX: PublicX; +>publicX : Symbol(publicX, Decl(objectSpreadNegative.ts, 9, 11)) >PublicX : Symbol(PublicX, Decl(objectSpreadNegative.ts, 5, 1)) -let privateOptionalX: PrivateOptionalX; ->privateOptionalX : Symbol(privateOptionalX, Decl(objectSpreadNegative.ts, 10, 3)) +declare let privateOptionalX: PrivateOptionalX; +>privateOptionalX : Symbol(privateOptionalX, Decl(objectSpreadNegative.ts, 10, 11)) >PrivateOptionalX : Symbol(PrivateOptionalX, Decl(objectSpreadNegative.ts, 0, 25)) let o2 = { ...publicX, ...privateOptionalX }; >o2 : Symbol(o2, Decl(objectSpreadNegative.ts, 11, 3)) ->publicX : Symbol(publicX, Decl(objectSpreadNegative.ts, 9, 3)) ->privateOptionalX : Symbol(privateOptionalX, Decl(objectSpreadNegative.ts, 10, 3)) +>publicX : Symbol(publicX, Decl(objectSpreadNegative.ts, 9, 11)) +>privateOptionalX : Symbol(privateOptionalX, Decl(objectSpreadNegative.ts, 10, 11)) let sn: number = o2.x; // error, x is private >sn : Symbol(sn, Decl(objectSpreadNegative.ts, 12, 3)) >o2 : Symbol(o2, Decl(objectSpreadNegative.ts, 11, 3)) -let optionalString: { sn?: string }; ->optionalString : Symbol(optionalString, Decl(objectSpreadNegative.ts, 13, 3)) ->sn : Symbol(sn, Decl(objectSpreadNegative.ts, 13, 21)) +declare let optionalString: { sn?: string }; +>optionalString : Symbol(optionalString, Decl(objectSpreadNegative.ts, 13, 11)) +>sn : Symbol(sn, Decl(objectSpreadNegative.ts, 13, 29)) -let optionalNumber: { sn?: number }; ->optionalNumber : Symbol(optionalNumber, Decl(objectSpreadNegative.ts, 14, 3)) ->sn : Symbol(sn, Decl(objectSpreadNegative.ts, 14, 21)) +declare let optionalNumber: { sn?: number }; +>optionalNumber : Symbol(optionalNumber, Decl(objectSpreadNegative.ts, 14, 11)) +>sn : Symbol(sn, Decl(objectSpreadNegative.ts, 14, 29)) let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumber }; >allOptional : Symbol(allOptional, Decl(objectSpreadNegative.ts, 15, 3)) >sn : Symbol(sn, Decl(objectSpreadNegative.ts, 15, 18)) ->optionalString : Symbol(optionalString, Decl(objectSpreadNegative.ts, 13, 3)) ->optionalNumber : Symbol(optionalNumber, Decl(objectSpreadNegative.ts, 14, 3)) +>optionalString : Symbol(optionalString, Decl(objectSpreadNegative.ts, 13, 11)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpreadNegative.ts, 14, 11)) // error, 'sn' is optional in source, required in target @@ -90,79 +90,159 @@ let duplicatedSpread = { ...o, ...o } >o : Symbol(o, Decl(objectSpreadNegative.ts, 0, 3)) >o : Symbol(o, Decl(objectSpreadNegative.ts, 0, 3)) +// Note: ignore changes the order that properties are printed +let ignore: { a: number, b: string } = +>ignore : Symbol(ignore, Decl(objectSpreadNegative.ts, 30, 3)) +>a : Symbol(a, Decl(objectSpreadNegative.ts, 30, 13)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 30, 24)) + + { b: 'ignored', ...o } +>b : Symbol(b, Decl(objectSpreadNegative.ts, 31, 5)) +>o : Symbol(o, Decl(objectSpreadNegative.ts, 0, 3)) + +let o3 = { a: 1, b: 'no' } +>o3 : Symbol(o3, Decl(objectSpreadNegative.ts, 33, 3)) +>a : Symbol(a, Decl(objectSpreadNegative.ts, 33, 10)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 33, 16)) + +let o4 = { b: 'yes', c: true } +>o4 : Symbol(o4, Decl(objectSpreadNegative.ts, 34, 3)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 34, 10)) +>c : Symbol(c, Decl(objectSpreadNegative.ts, 34, 20)) + +let combinedBefore: { a: number, b: string, c: boolean } = +>combinedBefore : Symbol(combinedBefore, Decl(objectSpreadNegative.ts, 35, 3)) +>a : Symbol(a, Decl(objectSpreadNegative.ts, 35, 21)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 35, 32)) +>c : Symbol(c, Decl(objectSpreadNegative.ts, 35, 43)) + + { b: 'ok', ...o3, ...o4 } +>b : Symbol(b, Decl(objectSpreadNegative.ts, 36, 5)) +>o3 : Symbol(o3, Decl(objectSpreadNegative.ts, 33, 3)) +>o4 : Symbol(o4, Decl(objectSpreadNegative.ts, 34, 3)) + +let combinedMid: { a: number, b: string, c: boolean } = +>combinedMid : Symbol(combinedMid, Decl(objectSpreadNegative.ts, 37, 3)) +>a : Symbol(a, Decl(objectSpreadNegative.ts, 37, 18)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 37, 29)) +>c : Symbol(c, Decl(objectSpreadNegative.ts, 37, 40)) + + { ...o3, b: 'ok', ...o4 } +>o3 : Symbol(o3, Decl(objectSpreadNegative.ts, 33, 3)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 38, 12)) +>o4 : Symbol(o4, Decl(objectSpreadNegative.ts, 34, 3)) + +let combinedNested: { a: number, b: boolean, c: string, d: string } = +>combinedNested : Symbol(combinedNested, Decl(objectSpreadNegative.ts, 39, 3)) +>a : Symbol(a, Decl(objectSpreadNegative.ts, 39, 21)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 39, 32)) +>c : Symbol(c, Decl(objectSpreadNegative.ts, 39, 44)) +>d : Symbol(d, Decl(objectSpreadNegative.ts, 39, 55)) + + { ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } +>a : Symbol(a, Decl(objectSpreadNegative.ts, 40, 10)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 40, 21)) +>c : Symbol(c, Decl(objectSpreadNegative.ts, 40, 31)) +>d : Symbol(d, Decl(objectSpreadNegative.ts, 40, 51)) +>a : Symbol(a, Decl(objectSpreadNegative.ts, 40, 75)) +>d : Symbol(d, Decl(objectSpreadNegative.ts, 40, 81)) + +let changeTypeBefore: { a: number, b: string } = +>changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpreadNegative.ts, 41, 3)) +>a : Symbol(a, Decl(objectSpreadNegative.ts, 41, 23)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 41, 34)) + + { a: 'wrong type?', ...o3 }; +>a : Symbol(a, Decl(objectSpreadNegative.ts, 42, 5)) +>o3 : Symbol(o3, Decl(objectSpreadNegative.ts, 33, 3)) + +let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = +>computedMiddle : Symbol(computedMiddle, Decl(objectSpreadNegative.ts, 43, 3)) +>a : Symbol(a, Decl(objectSpreadNegative.ts, 43, 21)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 43, 32)) +>c : Symbol(c, Decl(objectSpreadNegative.ts, 43, 43)) +>"in the middle" : Symbol("in the middle", Decl(objectSpreadNegative.ts, 43, 55)) + + { ...o3, ['in the middle']: 13, b: 'maybe?', ...o4 } +>o3 : Symbol(o3, Decl(objectSpreadNegative.ts, 33, 3)) +>['in the middle'] : Symbol(['in the middle'], Decl(objectSpreadNegative.ts, 44, 12)) +>'in the middle' : Symbol(['in the middle'], Decl(objectSpreadNegative.ts, 44, 12)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 44, 35)) +>o4 : Symbol(o4, Decl(objectSpreadNegative.ts, 34, 3)) + // primitives are not allowed, except for falsy ones let spreadNum = { ...12 }; ->spreadNum : Symbol(spreadNum, Decl(objectSpreadNegative.ts, 31, 3)) +>spreadNum : Symbol(spreadNum, Decl(objectSpreadNegative.ts, 47, 3)) let spreadSum = { ...1 + 1 }; ->spreadSum : Symbol(spreadSum, Decl(objectSpreadNegative.ts, 32, 3)) +>spreadSum : Symbol(spreadSum, Decl(objectSpreadNegative.ts, 48, 3)) let spreadZero = { ...0 }; ->spreadZero : Symbol(spreadZero, Decl(objectSpreadNegative.ts, 33, 3)) +>spreadZero : Symbol(spreadZero, Decl(objectSpreadNegative.ts, 49, 3)) spreadZero.toFixed(); // error, no methods even from a falsy number ->spreadZero : Symbol(spreadZero, Decl(objectSpreadNegative.ts, 33, 3)) +>spreadZero : Symbol(spreadZero, Decl(objectSpreadNegative.ts, 49, 3)) let spreadBool = { ...true }; ->spreadBool : Symbol(spreadBool, Decl(objectSpreadNegative.ts, 35, 3)) +>spreadBool : Symbol(spreadBool, Decl(objectSpreadNegative.ts, 51, 3)) spreadBool.valueOf(); ->spreadBool : Symbol(spreadBool, Decl(objectSpreadNegative.ts, 35, 3)) +>spreadBool : Symbol(spreadBool, Decl(objectSpreadNegative.ts, 51, 3)) let spreadStr = { ...'foo' }; ->spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 37, 3)) +>spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 53, 3)) spreadStr.length; // error, no 'length' ->spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 37, 3)) +>spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 53, 3)) spreadStr.charAt(1); // error, no methods either ->spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 37, 3)) +>spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 53, 3)) // functions are skipped let spreadFunc = { ...function () { } } ->spreadFunc : Symbol(spreadFunc, Decl(objectSpreadNegative.ts, 41, 3)) +>spreadFunc : Symbol(spreadFunc, Decl(objectSpreadNegative.ts, 57, 3)) spreadFunc(); // error, no call signature ->spreadFunc : Symbol(spreadFunc, Decl(objectSpreadNegative.ts, 41, 3)) +>spreadFunc : Symbol(spreadFunc, Decl(objectSpreadNegative.ts, 57, 3)) // write-only properties get skipped let setterOnly = { ...{ set b (bad: number) { } } }; ->setterOnly : Symbol(setterOnly, Decl(objectSpreadNegative.ts, 45, 3)) ->b : Symbol(b, Decl(objectSpreadNegative.ts, 45, 23)) ->bad : Symbol(bad, Decl(objectSpreadNegative.ts, 45, 31)) +>setterOnly : Symbol(setterOnly, Decl(objectSpreadNegative.ts, 61, 3)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 61, 23)) +>bad : Symbol(bad, Decl(objectSpreadNegative.ts, 61, 31)) setterOnly.b = 12; // error, 'b' does not exist ->setterOnly.b : Symbol(b, Decl(objectSpreadNegative.ts, 45, 23)) ->setterOnly : Symbol(setterOnly, Decl(objectSpreadNegative.ts, 45, 3)) ->b : Symbol(b, Decl(objectSpreadNegative.ts, 45, 23)) +>setterOnly.b : Symbol(b, Decl(objectSpreadNegative.ts, 61, 23)) +>setterOnly : Symbol(setterOnly, Decl(objectSpreadNegative.ts, 61, 3)) +>b : Symbol(b, Decl(objectSpreadNegative.ts, 61, 23)) // methods are skipped because they aren't enumerable class C { p = 1; m() { } } ->C : Symbol(C, Decl(objectSpreadNegative.ts, 46, 18)) ->p : Symbol(C.p, Decl(objectSpreadNegative.ts, 49, 9)) ->m : Symbol(C.m, Decl(objectSpreadNegative.ts, 49, 16)) +>C : Symbol(C, Decl(objectSpreadNegative.ts, 62, 18)) +>p : Symbol(C.p, Decl(objectSpreadNegative.ts, 65, 9)) +>m : Symbol(C.m, Decl(objectSpreadNegative.ts, 65, 16)) let c: C = new C() ->c : Symbol(c, Decl(objectSpreadNegative.ts, 50, 3)) ->C : Symbol(C, Decl(objectSpreadNegative.ts, 46, 18)) ->C : Symbol(C, Decl(objectSpreadNegative.ts, 46, 18)) +>c : Symbol(c, Decl(objectSpreadNegative.ts, 66, 3)) +>C : Symbol(C, Decl(objectSpreadNegative.ts, 62, 18)) +>C : Symbol(C, Decl(objectSpreadNegative.ts, 62, 18)) let spreadC = { ...c } ->spreadC : Symbol(spreadC, Decl(objectSpreadNegative.ts, 51, 3)) ->c : Symbol(c, Decl(objectSpreadNegative.ts, 50, 3)) +>spreadC : Symbol(spreadC, Decl(objectSpreadNegative.ts, 67, 3)) +>c : Symbol(c, Decl(objectSpreadNegative.ts, 66, 3)) spreadC.m(); // error 'm' is not in '{ ... c }' ->spreadC : Symbol(spreadC, Decl(objectSpreadNegative.ts, 51, 3)) +>spreadC : Symbol(spreadC, Decl(objectSpreadNegative.ts, 67, 3)) // non primitive let obj: object = { a: 123 }; ->obj : Symbol(obj, Decl(objectSpreadNegative.ts, 55, 3)) ->a : Symbol(a, Decl(objectSpreadNegative.ts, 55, 19)) +>obj : Symbol(obj, Decl(objectSpreadNegative.ts, 71, 3)) +>a : Symbol(a, Decl(objectSpreadNegative.ts, 71, 19)) let spreadObj = { ...obj }; ->spreadObj : Symbol(spreadObj, Decl(objectSpreadNegative.ts, 56, 3)) ->obj : Symbol(obj, Decl(objectSpreadNegative.ts, 55, 3)) +>spreadObj : Symbol(spreadObj, Decl(objectSpreadNegative.ts, 72, 3)) +>obj : Symbol(obj, Decl(objectSpreadNegative.ts, 71, 3)) spreadObj.a; // error 'a' is not in {} ->spreadObj : Symbol(spreadObj, Decl(objectSpreadNegative.ts, 56, 3)) +>spreadObj : Symbol(spreadObj, Decl(objectSpreadNegative.ts, 72, 3)) diff --git a/tests/baselines/reference/objectSpreadNegative.types b/tests/baselines/reference/objectSpreadNegative.types index 351522d896121..a9f0a0f0774f7 100644 --- a/tests/baselines/reference/objectSpreadNegative.types +++ b/tests/baselines/reference/objectSpreadNegative.types @@ -12,7 +12,7 @@ class PrivateOptionalX { >PrivateOptionalX : PrivateOptionalX private x?: number; ->x : number +>x : number | undefined } class PublicX { >PublicX : PublicX @@ -20,10 +20,10 @@ class PublicX { public x: number; >x : number } -let publicX: PublicX; +declare let publicX: PublicX; >publicX : PublicX -let privateOptionalX: PrivateOptionalX; +declare let privateOptionalX: PrivateOptionalX; >privateOptionalX : PrivateOptionalX let o2 = { ...publicX, ...privateOptionalX }; @@ -38,20 +38,20 @@ let sn: number = o2.x; // error, x is private >o2 : {} >x : any -let optionalString: { sn?: string }; ->optionalString : { sn?: string; } ->sn : string +declare let optionalString: { sn?: string }; +>optionalString : { sn?: string | undefined; } +>sn : string | undefined -let optionalNumber: { sn?: number }; ->optionalNumber : { sn?: number; } ->sn : number +declare let optionalNumber: { sn?: number }; +>optionalNumber : { sn?: number | undefined; } +>sn : number | undefined let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumber }; >allOptional : { sn: string | number; } >sn : string | number ->{ ...optionalString, ...optionalNumber } : { sn?: string | number; } ->optionalString : { sn?: string; } ->optionalNumber : { sn?: number; } +>{ ...optionalString, ...optionalNumber } : { sn?: string | number | undefined; } +>optionalString : { sn?: string | undefined; } +>optionalNumber : { sn?: number | undefined; } // error, 'sn' is optional in source, required in target @@ -109,6 +109,113 @@ let duplicatedSpread = { ...o, ...o } >o : { a: number; b: string; } >o : { a: number; b: string; } +// Note: ignore changes the order that properties are printed +let ignore: { a: number, b: string } = +>ignore : { a: number; b: string; } +>a : number +>b : string + + { b: 'ignored', ...o } +>{ b: 'ignored', ...o } : { a: number; b: string; } +>b : string +>'ignored' : "ignored" +>o : { a: number; b: string; } + +let o3 = { a: 1, b: 'no' } +>o3 : { a: number; b: string; } +>{ a: 1, b: 'no' } : { a: number; b: string; } +>a : number +>1 : 1 +>b : string +>'no' : "no" + +let o4 = { b: 'yes', c: true } +>o4 : { b: string; c: boolean; } +>{ b: 'yes', c: true } : { b: string; c: boolean; } +>b : string +>'yes' : "yes" +>c : boolean +>true : true + +let combinedBefore: { a: number, b: string, c: boolean } = +>combinedBefore : { a: number; b: string; c: boolean; } +>a : number +>b : string +>c : boolean + + { b: 'ok', ...o3, ...o4 } +>{ b: 'ok', ...o3, ...o4 } : { b: string; c: boolean; a: number; } +>b : string +>'ok' : "ok" +>o3 : { a: number; b: string; } +>o4 : { b: string; c: boolean; } + +let combinedMid: { a: number, b: string, c: boolean } = +>combinedMid : { a: number; b: string; c: boolean; } +>a : number +>b : string +>c : boolean + + { ...o3, b: 'ok', ...o4 } +>{ ...o3, b: 'ok', ...o4 } : { b: string; c: boolean; a: number; } +>o3 : { a: number; b: string; } +>b : string +>'ok' : "ok" +>o4 : { b: string; c: boolean; } + +let combinedNested: { a: number, b: boolean, c: string, d: string } = +>combinedNested : { a: number; b: boolean; c: string; d: string; } +>a : number +>b : boolean +>c : string +>d : string + + { ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } +>{ ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } } : { a: number; d: string; b: false; c: string; } +>{ a: 4, ...{ b: false, c: 'overriden' } } : { b: false; c: string; a: number; } +>a : number +>4 : 4 +>{ b: false, c: 'overriden' } : { b: false; c: string; } +>b : false +>false : false +>c : string +>'overriden' : "overriden" +>d : string +>'actually new' : "actually new" +>{ a: 5, d: 'maybe new' } : { a: number; d: string; } +>a : number +>5 : 5 +>d : string +>'maybe new' : "maybe new" + +let changeTypeBefore: { a: number, b: string } = +>changeTypeBefore : { a: number; b: string; } +>a : number +>b : string + + { a: 'wrong type?', ...o3 }; +>{ a: 'wrong type?', ...o3 } : { a: number; b: string; } +>a : string +>'wrong type?' : "wrong type?" +>o3 : { a: number; b: string; } + +let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = +>computedMiddle : { a: number; b: string; c: boolean; "in the middle": number; } +>a : number +>b : string +>c : boolean +>"in the middle" : number + + { ...o3, ['in the middle']: 13, b: 'maybe?', ...o4 } +>{ ...o3, ['in the middle']: 13, b: 'maybe?', ...o4 } : { b: string; c: boolean; "in the middle": number; a: number; } +>o3 : { a: number; b: string; } +>['in the middle'] : number +>'in the middle' : "in the middle" +>13 : 13 +>b : string +>'maybe?' : "maybe?" +>o4 : { b: string; c: boolean; } + // primitives are not allowed, except for falsy ones let spreadNum = { ...12 }; >spreadNum : any diff --git a/tests/baselines/reference/spreadOverwritesProperty.js b/tests/baselines/reference/spreadOverwritesProperty.js new file mode 100644 index 0000000000000..bf8d28ae73249 --- /dev/null +++ b/tests/baselines/reference/spreadOverwritesProperty.js @@ -0,0 +1,37 @@ +//// [spreadOverwritesProperty.ts] +// without strict null checks, none of these should be an error +declare var ab: { a: number, b: number }; +declare var abq: { a: number, b?: number }; +var unused1 = { b: 1, ...ab } +var unused2 = { ...ab, ...ab } +var unused3 = { b: 1, ...abq } + +function g(obj: { x: number | undefined }) { + return { x: 1, ...obj }; +} +function h(obj: { x: number }) { + return { x: 1, ...obj }; +} + + +//// [spreadOverwritesProperty.js] +var __assign = (this && this.__assign) || function () { + __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; + }; + return __assign.apply(this, arguments); +}; +var unused1 = __assign({ b: 1 }, ab); +var unused2 = __assign(__assign({}, ab), ab); +var unused3 = __assign({ b: 1 }, abq); +function g(obj) { + return __assign({ x: 1 }, obj); +} +function h(obj) { + return __assign({ x: 1 }, obj); +} diff --git a/tests/baselines/reference/spreadOverwritesProperty.symbols b/tests/baselines/reference/spreadOverwritesProperty.symbols new file mode 100644 index 0000000000000..414d8c07371bd --- /dev/null +++ b/tests/baselines/reference/spreadOverwritesProperty.symbols @@ -0,0 +1,46 @@ +=== tests/cases/conformance/types/spread/spreadOverwritesProperty.ts === +// without strict null checks, none of these should be an error +declare var ab: { a: number, b: number }; +>ab : Symbol(ab, Decl(spreadOverwritesProperty.ts, 1, 11)) +>a : Symbol(a, Decl(spreadOverwritesProperty.ts, 1, 17)) +>b : Symbol(b, Decl(spreadOverwritesProperty.ts, 1, 28)) + +declare var abq: { a: number, b?: number }; +>abq : Symbol(abq, Decl(spreadOverwritesProperty.ts, 2, 11)) +>a : Symbol(a, Decl(spreadOverwritesProperty.ts, 2, 18)) +>b : Symbol(b, Decl(spreadOverwritesProperty.ts, 2, 29)) + +var unused1 = { b: 1, ...ab } +>unused1 : Symbol(unused1, Decl(spreadOverwritesProperty.ts, 3, 3)) +>b : Symbol(b, Decl(spreadOverwritesProperty.ts, 3, 15)) +>ab : Symbol(ab, Decl(spreadOverwritesProperty.ts, 1, 11)) + +var unused2 = { ...ab, ...ab } +>unused2 : Symbol(unused2, Decl(spreadOverwritesProperty.ts, 4, 3)) +>ab : Symbol(ab, Decl(spreadOverwritesProperty.ts, 1, 11)) +>ab : Symbol(ab, Decl(spreadOverwritesProperty.ts, 1, 11)) + +var unused3 = { b: 1, ...abq } +>unused3 : Symbol(unused3, Decl(spreadOverwritesProperty.ts, 5, 3)) +>b : Symbol(b, Decl(spreadOverwritesProperty.ts, 5, 15)) +>abq : Symbol(abq, Decl(spreadOverwritesProperty.ts, 2, 11)) + +function g(obj: { x: number | undefined }) { +>g : Symbol(g, Decl(spreadOverwritesProperty.ts, 5, 30)) +>obj : Symbol(obj, Decl(spreadOverwritesProperty.ts, 7, 11)) +>x : Symbol(x, Decl(spreadOverwritesProperty.ts, 7, 17)) + + return { x: 1, ...obj }; +>x : Symbol(x, Decl(spreadOverwritesProperty.ts, 8, 12)) +>obj : Symbol(obj, Decl(spreadOverwritesProperty.ts, 7, 11)) +} +function h(obj: { x: number }) { +>h : Symbol(h, Decl(spreadOverwritesProperty.ts, 9, 1)) +>obj : Symbol(obj, Decl(spreadOverwritesProperty.ts, 10, 11)) +>x : Symbol(x, Decl(spreadOverwritesProperty.ts, 10, 17)) + + return { x: 1, ...obj }; +>x : Symbol(x, Decl(spreadOverwritesProperty.ts, 11, 12)) +>obj : Symbol(obj, Decl(spreadOverwritesProperty.ts, 10, 11)) +} + diff --git a/tests/baselines/reference/spreadOverwritesProperty.types b/tests/baselines/reference/spreadOverwritesProperty.types new file mode 100644 index 0000000000000..3118919a5f7ff --- /dev/null +++ b/tests/baselines/reference/spreadOverwritesProperty.types @@ -0,0 +1,55 @@ +=== tests/cases/conformance/types/spread/spreadOverwritesProperty.ts === +// without strict null checks, none of these should be an error +declare var ab: { a: number, b: number }; +>ab : { a: number; b: number; } +>a : number +>b : number + +declare var abq: { a: number, b?: number }; +>abq : { a: number; b?: number; } +>a : number +>b : number + +var unused1 = { b: 1, ...ab } +>unused1 : { a: number; b: number; } +>{ b: 1, ...ab } : { a: number; b: number; } +>b : number +>1 : 1 +>ab : { a: number; b: number; } + +var unused2 = { ...ab, ...ab } +>unused2 : { a: number; b: number; } +>{ ...ab, ...ab } : { a: number; b: number; } +>ab : { a: number; b: number; } +>ab : { a: number; b: number; } + +var unused3 = { b: 1, ...abq } +>unused3 : { a: number; b: number; } +>{ b: 1, ...abq } : { a: number; b: number; } +>b : number +>1 : 1 +>abq : { a: number; b?: number; } + +function g(obj: { x: number | undefined }) { +>g : (obj: { x: number; }) => { x: number; } +>obj : { x: number; } +>x : number + + return { x: 1, ...obj }; +>{ x: 1, ...obj } : { x: number; } +>x : number +>1 : 1 +>obj : { x: number; } +} +function h(obj: { x: number }) { +>h : (obj: { x: number; }) => { x: number; } +>obj : { x: number; } +>x : number + + return { x: 1, ...obj }; +>{ x: 1, ...obj } : { x: number; } +>x : number +>1 : 1 +>obj : { x: number; } +} + diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt b/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt new file mode 100644 index 0000000000000..9d9602c621ab1 --- /dev/null +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt @@ -0,0 +1,24 @@ +tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(3,17): error TS2783: 'b' is specified more than once, so this usage will be overwritten. +tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(13,14): error TS2783: 'x' is specified more than once, so this usage will be overwritten. + + +==== tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts (2 errors) ==== + declare var ab: { a: number, b: number }; + declare var abq: { a: number, b?: number }; + var unused1 = { b: 1, ...ab } // error + ~~~~ +!!! error TS2783: 'b' is specified more than once, so this usage will be overwritten. + var unused2 = { ...ab, ...ab } // ok, overwritten error doesn't apply to spreads + var unused3 = { b: 1, ...abq } // ok, abq might have b: undefined + function g(obj: { x: number | undefined }) { + return { x: 1, ...obj }; // ok, obj might have x: undefined + } + function f(obj: { x: number } | undefined) { + return { x: 1, ...obj }; // ok, obj might be undefined + } + function h(obj: { x: number } | { x: string }) { + return { x: 1, ...obj } // error + ~~~~ +!!! error TS2783: 'x' is specified more than once, so this usage will be overwritten. + } + \ No newline at end of file diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.js b/tests/baselines/reference/spreadOverwritesPropertyStrict.js new file mode 100644 index 0000000000000..0b8e6b5860e84 --- /dev/null +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.js @@ -0,0 +1,42 @@ +//// [spreadOverwritesPropertyStrict.ts] +declare var ab: { a: number, b: number }; +declare var abq: { a: number, b?: number }; +var unused1 = { b: 1, ...ab } // error +var unused2 = { ...ab, ...ab } // ok, overwritten error doesn't apply to spreads +var unused3 = { b: 1, ...abq } // ok, abq might have b: undefined +function g(obj: { x: number | undefined }) { + return { x: 1, ...obj }; // ok, obj might have x: undefined +} +function f(obj: { x: number } | undefined) { + return { x: 1, ...obj }; // ok, obj might be undefined +} +function h(obj: { x: number } | { x: string }) { + return { x: 1, ...obj } // error +} + + +//// [spreadOverwritesPropertyStrict.js] +"use strict"; +var __assign = (this && this.__assign) || function () { + __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; + }; + return __assign.apply(this, arguments); +}; +var unused1 = __assign({ b: 1 }, ab); // error +var unused2 = __assign(__assign({}, ab), ab); // ok, overwritten error doesn't apply to spreads +var unused3 = __assign({ b: 1 }, abq); // ok, abq might have b: undefined +function g(obj) { + return __assign({ x: 1 }, obj); // ok, obj might have x: undefined +} +function f(obj) { + return __assign({ x: 1 }, obj); // ok, obj might be undefined +} +function h(obj) { + return __assign({ x: 1 }, obj); // error +} diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols b/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols new file mode 100644 index 0000000000000..90ac5010b0879 --- /dev/null +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols @@ -0,0 +1,55 @@ +=== tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts === +declare var ab: { a: number, b: number }; +>ab : Symbol(ab, Decl(spreadOverwritesPropertyStrict.ts, 0, 11)) +>a : Symbol(a, Decl(spreadOverwritesPropertyStrict.ts, 0, 17)) +>b : Symbol(b, Decl(spreadOverwritesPropertyStrict.ts, 0, 28)) + +declare var abq: { a: number, b?: number }; +>abq : Symbol(abq, Decl(spreadOverwritesPropertyStrict.ts, 1, 11)) +>a : Symbol(a, Decl(spreadOverwritesPropertyStrict.ts, 1, 18)) +>b : Symbol(b, Decl(spreadOverwritesPropertyStrict.ts, 1, 29)) + +var unused1 = { b: 1, ...ab } // error +>unused1 : Symbol(unused1, Decl(spreadOverwritesPropertyStrict.ts, 2, 3)) +>b : Symbol(b, Decl(spreadOverwritesPropertyStrict.ts, 2, 15)) +>ab : Symbol(ab, Decl(spreadOverwritesPropertyStrict.ts, 0, 11)) + +var unused2 = { ...ab, ...ab } // ok, overwritten error doesn't apply to spreads +>unused2 : Symbol(unused2, Decl(spreadOverwritesPropertyStrict.ts, 3, 3)) +>ab : Symbol(ab, Decl(spreadOverwritesPropertyStrict.ts, 0, 11)) +>ab : Symbol(ab, Decl(spreadOverwritesPropertyStrict.ts, 0, 11)) + +var unused3 = { b: 1, ...abq } // ok, abq might have b: undefined +>unused3 : Symbol(unused3, Decl(spreadOverwritesPropertyStrict.ts, 4, 3)) +>b : Symbol(b, Decl(spreadOverwritesPropertyStrict.ts, 4, 15)) +>abq : Symbol(abq, Decl(spreadOverwritesPropertyStrict.ts, 1, 11)) + +function g(obj: { x: number | undefined }) { +>g : Symbol(g, Decl(spreadOverwritesPropertyStrict.ts, 4, 30)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 5, 11)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 5, 17)) + + return { x: 1, ...obj }; // ok, obj might have x: undefined +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 6, 12)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 5, 11)) +} +function f(obj: { x: number } | undefined) { +>f : Symbol(f, Decl(spreadOverwritesPropertyStrict.ts, 7, 1)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 8, 11)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 8, 17)) + + return { x: 1, ...obj }; // ok, obj might be undefined +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 9, 12)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 8, 11)) +} +function h(obj: { x: number } | { x: string }) { +>h : Symbol(h, Decl(spreadOverwritesPropertyStrict.ts, 10, 1)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 11, 11)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 11, 17)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 11, 33)) + + return { x: 1, ...obj } // error +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 12, 12)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 11, 11)) +} + diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.types b/tests/baselines/reference/spreadOverwritesPropertyStrict.types new file mode 100644 index 0000000000000..73ca7e659e234 --- /dev/null +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.types @@ -0,0 +1,66 @@ +=== tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts === +declare var ab: { a: number, b: number }; +>ab : { a: number; b: number; } +>a : number +>b : number + +declare var abq: { a: number, b?: number }; +>abq : { a: number; b?: number | undefined; } +>a : number +>b : number | undefined + +var unused1 = { b: 1, ...ab } // error +>unused1 : { a: number; b: number; } +>{ b: 1, ...ab } : { a: number; b: number; } +>b : number +>1 : 1 +>ab : { a: number; b: number; } + +var unused2 = { ...ab, ...ab } // ok, overwritten error doesn't apply to spreads +>unused2 : { a: number; b: number; } +>{ ...ab, ...ab } : { a: number; b: number; } +>ab : { a: number; b: number; } +>ab : { a: number; b: number; } + +var unused3 = { b: 1, ...abq } // ok, abq might have b: undefined +>unused3 : { a: number; b: number; } +>{ b: 1, ...abq } : { a: number; b: number; } +>b : number +>1 : 1 +>abq : { a: number; b?: number | undefined; } + +function g(obj: { x: number | undefined }) { +>g : (obj: { x: number | undefined; }) => { x: number | undefined; } +>obj : { x: number | undefined; } +>x : number | undefined + + return { x: 1, ...obj }; // ok, obj might have x: undefined +>{ x: 1, ...obj } : { x: number | undefined; } +>x : number +>1 : 1 +>obj : { x: number | undefined; } +} +function f(obj: { x: number } | undefined) { +>f : (obj: { x: number; } | undefined) => { x: number; } +>obj : { x: number; } | undefined +>x : number + + return { x: 1, ...obj }; // ok, obj might be undefined +>{ x: 1, ...obj } : { x: number; } +>x : number +>1 : 1 +>obj : { x: number; } | undefined +} +function h(obj: { x: number } | { x: string }) { +>h : (obj: { x: number; } | { x: string; }) => { x: number; } | { x: string; } +>obj : { x: number; } | { x: string; } +>x : number +>x : string + + return { x: 1, ...obj } // error +>{ x: 1, ...obj } : { x: number; } | { x: string; } +>x : number +>1 : 1 +>obj : { x: number; } | { x: string; } +} + diff --git a/tests/cases/conformance/types/spread/objectSpreadNegative.ts b/tests/cases/conformance/types/spread/objectSpreadNegative.ts index dfc902748ecb9..00dfd440667b3 100644 --- a/tests/cases/conformance/types/spread/objectSpreadNegative.ts +++ b/tests/cases/conformance/types/spread/objectSpreadNegative.ts @@ -1,4 +1,5 @@ // @target: es5 +// @strictNullChecks: true let o = { a: 1, b: 'no' } /// private propagates @@ -8,12 +9,12 @@ class PrivateOptionalX { class PublicX { public x: number; } -let publicX: PublicX; -let privateOptionalX: PrivateOptionalX; +declare let publicX: PublicX; +declare let privateOptionalX: PrivateOptionalX; let o2 = { ...publicX, ...privateOptionalX }; let sn: number = o2.x; // error, x is private -let optionalString: { sn?: string }; -let optionalNumber: { sn?: number }; +declare let optionalString: { sn?: string }; +declare let optionalNumber: { sn?: number }; let allOptional: { sn: string | number } = { ...optionalString, ...optionalNumber }; // error, 'sn' is optional in source, required in target diff --git a/tests/cases/conformance/types/spread/spreadOverwritesProperty.ts b/tests/cases/conformance/types/spread/spreadOverwritesProperty.ts index 909fe5434f68c..bfbb11348d93e 100644 --- a/tests/cases/conformance/types/spread/spreadOverwritesProperty.ts +++ b/tests/cases/conformance/types/spread/spreadOverwritesProperty.ts @@ -1,3 +1,4 @@ +// without strict null checks, none of these should be an error declare var ab: { a: number, b: number }; declare var abq: { a: number, b?: number }; var unused1 = { b: 1, ...ab } @@ -5,7 +6,8 @@ var unused2 = { ...ab, ...ab } var unused3 = { b: 1, ...abq } function g(obj: { x: number | undefined }) { - return { x: 1, ...obj }; // should be allowed because of undefined + return { x: 1, ...obj }; } function h(obj: { x: number }) { - return { x: 1, ...obj }; // should be allowed because we don't know about undefined + return { x: 1, ...obj }; +} diff --git a/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts b/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts index e2bf6da240fac..70e72d19910d0 100644 --- a/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts +++ b/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts @@ -1,12 +1,15 @@ // @strict: true declare var ab: { a: number, b: number }; declare var abq: { a: number, b?: number }; -var unused1 = { b: 1, ...ab } -var unused2 = { ...ab, ...ab } -var unused3 = { b: 1, ...abq } +var unused1 = { b: 1, ...ab } // error +var unused2 = { ...ab, ...ab } // ok, overwritten error doesn't apply to spreads +var unused3 = { b: 1, ...abq } // ok, abq might have b: undefined function g(obj: { x: number | undefined }) { - return { x: 1, ...obj }; // should be allowed because of undefined + return { x: 1, ...obj }; // ok, obj might have x: undefined } function f(obj: { x: number } | undefined) { - return { x: 1, ...obj }; + return { x: 1, ...obj }; // ok, obj might be undefined +} +function h(obj: { x: number } | { x: string }) { + return { x: 1, ...obj } // error } From ccdbad7d26c80ff3aae32e59d8c7664e27bb650b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 10 Feb 2020 15:51:29 -0800 Subject: [PATCH 06/11] make jsx tests stricter --- tests/baselines/reference/checkJsxChildrenProperty13.types | 4 ++-- .../baselines/reference/checkJsxChildrenProperty2.errors.txt | 3 ++- tests/baselines/reference/checkJsxChildrenProperty2.js | 3 ++- tests/cases/conformance/jsx/checkJsxChildrenProperty13.tsx | 1 + tests/cases/conformance/jsx/checkJsxChildrenProperty2.tsx | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/baselines/reference/checkJsxChildrenProperty13.types b/tests/baselines/reference/checkJsxChildrenProperty13.types index da159a74aa0e2..0e9542845fe2d 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty13.types +++ b/tests/baselines/reference/checkJsxChildrenProperty13.types @@ -27,9 +27,9 @@ class Button extends React.Component { >(
Hello World
) : JSX.Element >
Hello World
: JSX.Element >InnerButton : typeof InnerButton ->this.props : ButtonProp & { children?: React.ReactNode; } +>this.props : ButtonProp & { children?: string | number | boolean | {} | React.ReactElement | (string | number | boolean | any[] | React.ReactElement)[] | undefined; } >this : this ->props : ButtonProp & { children?: React.ReactNode; } +>props : ButtonProp & { children?: string | number | boolean | {} | React.ReactElement | (string | number | boolean | any[] | React.ReactElement)[] | undefined; } >children : string
Hello World
diff --git a/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt b/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt index 323f277e09bb1..29ebb4ad033ba 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt +++ b/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt @@ -68,4 +68,5 @@ tests/cases/conformance/jsx/file.tsx(49,6): error TS2746: This JSX tag's 'childr !!! error TS2746: This JSX tag's 'children' prop expects a single child of type 'string | Element', but multiple children were provided.
My Div
My Div
- ; \ No newline at end of file + ; + \ No newline at end of file diff --git a/tests/baselines/reference/checkJsxChildrenProperty2.js b/tests/baselines/reference/checkJsxChildrenProperty2.js index dd92bb5dba899..1320766b89aca 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty2.js +++ b/tests/baselines/reference/checkJsxChildrenProperty2.js @@ -50,7 +50,8 @@ let k5 =
My Div
My Div
-
; + ; + //// [file.jsx] "use strict"; diff --git a/tests/cases/conformance/jsx/checkJsxChildrenProperty13.tsx b/tests/cases/conformance/jsx/checkJsxChildrenProperty13.tsx index 0c2d25078646a..e7918999465ec 100644 --- a/tests/cases/conformance/jsx/checkJsxChildrenProperty13.tsx +++ b/tests/cases/conformance/jsx/checkJsxChildrenProperty13.tsx @@ -3,6 +3,7 @@ // @noLib: true // @skipLibCheck: true // @libFiles: react.d.ts,lib.d.ts +// @strictNullChecks: true import React = require('react'); diff --git a/tests/cases/conformance/jsx/checkJsxChildrenProperty2.tsx b/tests/cases/conformance/jsx/checkJsxChildrenProperty2.tsx index 632b9d5d84908..2f452a0aaf629 100644 --- a/tests/cases/conformance/jsx/checkJsxChildrenProperty2.tsx +++ b/tests/cases/conformance/jsx/checkJsxChildrenProperty2.tsx @@ -3,6 +3,7 @@ // @noLib: true // @skipLibCheck: true // @libFiles: react.d.ts,lib.d.ts +// @strictNullChecks: true import React = require('react'); @@ -55,4 +56,4 @@ let k5 =
My Div
My Div
-
; \ No newline at end of file + ; From 0703108d2fd5b5a469c0581dbd0ce531d4368fb2 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 10 Feb 2020 15:55:06 -0800 Subject: [PATCH 07/11] update semicolon error message --- .../reference/betterErrorForAccidentalCall.errors.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/betterErrorForAccidentalCall.errors.txt b/tests/baselines/reference/betterErrorForAccidentalCall.errors.txt index e381b522ec792..7575fa2ca7e9e 100644 --- a/tests/baselines/reference/betterErrorForAccidentalCall.errors.txt +++ b/tests/baselines/reference/betterErrorForAccidentalCall.errors.txt @@ -27,20 +27,20 @@ tests/cases/compiler/betterErrorForAccidentalCall.ts(13,1): error TS2349: This e ~~~~~ !!! error TS2349: This expression is not callable. !!! error TS2349: Type 'String' has no call signatures. -!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:7:1: Are you missing a semicolon here? +!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:7:1: Are you missing a semicolon? (1 as number).toString(); foo() ~~~~~ !!! error TS2349: This expression is not callable. !!! error TS2349: Type 'String' has no call signatures. -!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:10:1: Are you missing a semicolon here? +!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:10:1: Are you missing a semicolon? (1 + 2).toString(); foo() ~~~~~ !!! error TS2349: This expression is not callable. !!! error TS2349: Type 'String' has no call signatures. -!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:13:1: Are you missing a semicolon here? +!!! related TS2734 tests/cases/compiler/betterErrorForAccidentalCall.ts:13:1: Are you missing a semicolon? (1).toString(); \ No newline at end of file From 231eda7cea91adca87e7044b875febafcaf6d689 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 10 Feb 2020 16:07:40 -0800 Subject: [PATCH 08/11] use ?. because it is great --- src/compiler/checker.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 215b7dda41f19..872abb7491deb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16629,8 +16629,7 @@ namespace ts { } function isFromSpreadAssignment(prop: Symbol, container: Symbol) { - // TODO: Should use ?. now - return !(prop.valueDeclaration && container.valueDeclaration && prop.valueDeclaration.parent === container.valueDeclaration); + return prop.valueDeclaration?.parent !== container.valueDeclaration; } /** From 03bae3701cb9d1abc2e9a172fa94732ca938bd7b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 10 Feb 2020 16:16:35 -0800 Subject: [PATCH 09/11] use maybeTypeOfKind in new code --- src/compiler/checker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 872abb7491deb..73afcb7f36127 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13055,9 +13055,9 @@ namespace ts { if (right.flags & TypeFlags.Union) { const merged = tryMergeUnionOfObjectTypeAndEmptyObject(right as UnionType, readonly); if (merged) { - return getSpreadType(left, merged, symbol, objectFlags, readonly, !!(right.flags & TypeFlags.Nullable)); + return getSpreadType(left, merged, symbol, objectFlags, readonly, maybeTypeOfKind(right, TypeFlags.Nullable)); } - return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly, !!(right.flags & TypeFlags.Nullable))); + return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly, maybeTypeOfKind(right, TypeFlags.Nullable))); } if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) { return left; @@ -13126,7 +13126,7 @@ namespace ts { symbol && !isFromSpreadAssignment(leftProp, symbol) && isFromSpreadAssignment(rightProp, symbol) && - !(getFalsyFlags(rightType) & TypeFlags.Nullable)) { + !maybeTypeOfKind(rightType, TypeFlags.Nullable)) { error(leftProp.valueDeclaration, Diagnostics._0_is_specified_more_than_once_so_this_usage_will_be_overwritten, unescapeLeadingUnderscores(leftProp.escapedName)); } } From cfee8ba5fc749a4934fc938cbd10a3ff1b45c6d3 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 10 Feb 2020 16:20:09 -0800 Subject: [PATCH 10/11] restore jsx error --- src/compiler/checker.ts | 11 +++++++ .../checkJsxChildrenProperty13.errors.txt | 33 +++++++++++++++++++ .../checkJsxChildrenProperty2.errors.txt | 5 ++- 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/checkJsxChildrenProperty13.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 73afcb7f36127..e1b3c7e25fa5d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22676,6 +22676,7 @@ namespace ts { let spread: Type = emptyJsxObjectType; let hasSpreadAnyType = false; let typeToIntersect: Type | undefined; + let explicitlySpecifyChildrenAttribute = false; let objectFlags: ObjectFlags = ObjectFlags.JsxAttributes; const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement)); @@ -22694,6 +22695,9 @@ namespace ts { attributeSymbol.type = exprType; attributeSymbol.target = member; attributesTable.set(attributeSymbol.escapedName, attributeSymbol); + if (attributeDecl.name.escapedText === jsxChildrenPropertyName) { + explicitlySpecifyChildrenAttribute = true; + } } else { Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute); @@ -22727,6 +22731,13 @@ namespace ts { const childrenTypes: Type[] = checkJsxChildren(parent, checkMode); if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") { + // Error if there is a attribute named "children" explicitly specified and children element. + // This is because children element will overwrite the value from attributes. + // Note: we will not warn "children" attribute overwritten if "children" attribute is specified in object spread. + if (explicitlySpecifyChildrenAttribute) { + error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, unescapeLeadingUnderscores(jsxChildrenPropertyName)); + } + const contextualType = getApparentTypeOfContextualType(openingLikeElement.attributes); const childrenContextualType = contextualType && getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName); // If there are children in the body of JSX element, create dummy attribute "children" with the union of children types so that it will pass the attribute checking process diff --git a/tests/baselines/reference/checkJsxChildrenProperty13.errors.txt b/tests/baselines/reference/checkJsxChildrenProperty13.errors.txt new file mode 100644 index 0000000000000..c926980cab11f --- /dev/null +++ b/tests/baselines/reference/checkJsxChildrenProperty13.errors.txt @@ -0,0 +1,33 @@ +tests/cases/conformance/jsx/file.tsx(12,30): error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. + + +==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== + import React = require('react'); + + interface ButtonProp { + a: number, + b: string, + children: Button; + } + + class Button extends React.Component { + render() { + // Error children are specified twice + return ( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. +
Hello World
+
); + } + } + + interface InnerButtonProp { + a: number + } + + class InnerButton extends React.Component { + render() { + return (); + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt b/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt index 29ebb4ad033ba..23b6b7287147d 100644 --- a/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt +++ b/tests/baselines/reference/checkJsxChildrenProperty2.errors.txt @@ -1,11 +1,12 @@ tests/cases/conformance/jsx/file.tsx(14,10): error TS2741: Property 'children' is missing in type '{ a: number; b: string; }' but required in type 'Prop'. +tests/cases/conformance/jsx/file.tsx(17,11): error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. tests/cases/conformance/jsx/file.tsx(31,6): error TS2746: This JSX tag's 'children' prop expects a single child of type 'string | Element', but multiple children were provided. tests/cases/conformance/jsx/file.tsx(37,6): error TS2746: This JSX tag's 'children' prop expects a single child of type 'string | Element', but multiple children were provided. tests/cases/conformance/jsx/file.tsx(43,6): error TS2746: This JSX tag's 'children' prop expects a single child of type 'string | Element', but multiple children were provided. tests/cases/conformance/jsx/file.tsx(49,6): error TS2746: This JSX tag's 'children' prop expects a single child of type 'string | Element', but multiple children were provided. -==== tests/cases/conformance/jsx/file.tsx (5 errors) ==== +==== tests/cases/conformance/jsx/file.tsx (6 errors) ==== import React = require('react'); interface Prop { @@ -26,6 +27,8 @@ tests/cases/conformance/jsx/file.tsx(49,6): error TS2746: This JSX tag's 'childr let k0 = + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten. hi hi hi! ; From 5cae3bdaa95b743a1134374174b26370aa49f830 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 11 Feb 2020 09:13:53 -0800 Subject: [PATCH 11/11] add tests --- .../spreadOverwritesPropertyStrict.errors.txt | 4 +- .../spreadOverwritesPropertyStrict.js | 4 ++ .../spreadOverwritesPropertyStrict.symbols | 42 ++++++++++++------- .../spreadOverwritesPropertyStrict.types | 14 +++++++ .../spread/spreadOverwritesPropertyStrict.ts | 2 + 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt b/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt index 9d9602c621ab1..4abf968184b6f 100644 --- a/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(3,17): error TS2783: 'b' is specified more than once, so this usage will be overwritten. -tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(13,14): error TS2783: 'x' is specified more than once, so this usage will be overwritten. +tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(15,14): error TS2783: 'x' is specified more than once, so this usage will be overwritten. ==== tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts (2 errors) ==== @@ -10,6 +10,8 @@ tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(13,14): e !!! error TS2783: 'b' is specified more than once, so this usage will be overwritten. var unused2 = { ...ab, ...ab } // ok, overwritten error doesn't apply to spreads var unused3 = { b: 1, ...abq } // ok, abq might have b: undefined + var unused4 = { ...ab, b: 1 } // ok, we don't care that b in ab is overwritten + var unused5 = { ...abq, b: 1 } // ok function g(obj: { x: number | undefined }) { return { x: 1, ...obj }; // ok, obj might have x: undefined } diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.js b/tests/baselines/reference/spreadOverwritesPropertyStrict.js index 0b8e6b5860e84..001f134098404 100644 --- a/tests/baselines/reference/spreadOverwritesPropertyStrict.js +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.js @@ -4,6 +4,8 @@ declare var abq: { a: number, b?: number }; var unused1 = { b: 1, ...ab } // error var unused2 = { ...ab, ...ab } // ok, overwritten error doesn't apply to spreads var unused3 = { b: 1, ...abq } // ok, abq might have b: undefined +var unused4 = { ...ab, b: 1 } // ok, we don't care that b in ab is overwritten +var unused5 = { ...abq, b: 1 } // ok function g(obj: { x: number | undefined }) { return { x: 1, ...obj }; // ok, obj might have x: undefined } @@ -31,6 +33,8 @@ var __assign = (this && this.__assign) || function () { var unused1 = __assign({ b: 1 }, ab); // error var unused2 = __assign(__assign({}, ab), ab); // ok, overwritten error doesn't apply to spreads var unused3 = __assign({ b: 1 }, abq); // ok, abq might have b: undefined +var unused4 = __assign(__assign({}, ab), { b: 1 }); // ok, we don't care that b in ab is overwritten +var unused5 = __assign(__assign({}, abq), { b: 1 }); // ok function g(obj) { return __assign({ x: 1 }, obj); // ok, obj might have x: undefined } diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols b/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols index 90ac5010b0879..02e1e4037519d 100644 --- a/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols @@ -24,32 +24,42 @@ var unused3 = { b: 1, ...abq } // ok, abq might have b: undefined >b : Symbol(b, Decl(spreadOverwritesPropertyStrict.ts, 4, 15)) >abq : Symbol(abq, Decl(spreadOverwritesPropertyStrict.ts, 1, 11)) +var unused4 = { ...ab, b: 1 } // ok, we don't care that b in ab is overwritten +>unused4 : Symbol(unused4, Decl(spreadOverwritesPropertyStrict.ts, 5, 3)) +>ab : Symbol(ab, Decl(spreadOverwritesPropertyStrict.ts, 0, 11)) +>b : Symbol(b, Decl(spreadOverwritesPropertyStrict.ts, 5, 22)) + +var unused5 = { ...abq, b: 1 } // ok +>unused5 : Symbol(unused5, Decl(spreadOverwritesPropertyStrict.ts, 6, 3)) +>abq : Symbol(abq, Decl(spreadOverwritesPropertyStrict.ts, 1, 11)) +>b : Symbol(b, Decl(spreadOverwritesPropertyStrict.ts, 6, 23)) + function g(obj: { x: number | undefined }) { ->g : Symbol(g, Decl(spreadOverwritesPropertyStrict.ts, 4, 30)) ->obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 5, 11)) ->x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 5, 17)) +>g : Symbol(g, Decl(spreadOverwritesPropertyStrict.ts, 6, 30)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 7, 11)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 7, 17)) return { x: 1, ...obj }; // ok, obj might have x: undefined ->x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 6, 12)) ->obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 5, 11)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 8, 12)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 7, 11)) } function f(obj: { x: number } | undefined) { ->f : Symbol(f, Decl(spreadOverwritesPropertyStrict.ts, 7, 1)) ->obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 8, 11)) ->x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 8, 17)) +>f : Symbol(f, Decl(spreadOverwritesPropertyStrict.ts, 9, 1)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 10, 11)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 10, 17)) return { x: 1, ...obj }; // ok, obj might be undefined ->x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 9, 12)) ->obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 8, 11)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 11, 12)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 10, 11)) } function h(obj: { x: number } | { x: string }) { ->h : Symbol(h, Decl(spreadOverwritesPropertyStrict.ts, 10, 1)) ->obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 11, 11)) ->x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 11, 17)) ->x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 11, 33)) +>h : Symbol(h, Decl(spreadOverwritesPropertyStrict.ts, 12, 1)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 13, 11)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 13, 17)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 13, 33)) return { x: 1, ...obj } // error ->x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 12, 12)) ->obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 11, 11)) +>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 14, 12)) +>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 13, 11)) } diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.types b/tests/baselines/reference/spreadOverwritesPropertyStrict.types index 73ca7e659e234..55c142da247f5 100644 --- a/tests/baselines/reference/spreadOverwritesPropertyStrict.types +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.types @@ -29,6 +29,20 @@ var unused3 = { b: 1, ...abq } // ok, abq might have b: undefined >1 : 1 >abq : { a: number; b?: number | undefined; } +var unused4 = { ...ab, b: 1 } // ok, we don't care that b in ab is overwritten +>unused4 : { b: number; a: number; } +>{ ...ab, b: 1 } : { b: number; a: number; } +>ab : { a: number; b: number; } +>b : number +>1 : 1 + +var unused5 = { ...abq, b: 1 } // ok +>unused5 : { b: number; a: number; } +>{ ...abq, b: 1 } : { b: number; a: number; } +>abq : { a: number; b?: number | undefined; } +>b : number +>1 : 1 + function g(obj: { x: number | undefined }) { >g : (obj: { x: number | undefined; }) => { x: number | undefined; } >obj : { x: number | undefined; } diff --git a/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts b/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts index 70e72d19910d0..65d53dcd77533 100644 --- a/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts +++ b/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts @@ -4,6 +4,8 @@ declare var abq: { a: number, b?: number }; var unused1 = { b: 1, ...ab } // error var unused2 = { ...ab, ...ab } // ok, overwritten error doesn't apply to spreads var unused3 = { b: 1, ...abq } // ok, abq might have b: undefined +var unused4 = { ...ab, b: 1 } // ok, we don't care that b in ab is overwritten +var unused5 = { ...abq, b: 1 } // ok function g(obj: { x: number | undefined }) { return { x: 1, ...obj }; // ok, obj might have x: undefined }