Compare commits

...

4 commits

Author SHA1 Message Date
Nathan Shively-Sanders ed7a75b379 Quck and dirty fix for union problems
Doesn't fix JSX problems
2018-10-12 08:33:30 -07:00
Nathan Shively-Sanders aa7247bd74 Merge branch 'master' into error-property-overwritten-by-later-spread 2018-10-11 15:55:57 -07:00
Nathan Shively-Sanders 3d6450af9f Merge branch 'master' into error-property-overwritten-by-later-spread 2018-10-11 15:02:24 -07:00
Nathan Shively-Sanders b5fc5c0ed8 Error: Property is overwritten by later spread
Move the checking from JSX to getSpreadType so that normal objects get
the error too.

Also reword the missing semicolon related error to be less silly.
2018-10-09 15:11:21 -07:00
24 changed files with 878 additions and 582 deletions

View file

@ -9806,7 +9806,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, typeFlags: TypeFlags, objectFlags: ObjectFlags): Type {
function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, typeFlags: TypeFlags, objectFlags: ObjectFlags, isUnion?: boolean): Type {
if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) {
return anyType;
}
@ -9820,10 +9820,10 @@ namespace ts {
return left;
}
if (left.flags & TypeFlags.Union) {
return mapType(left, t => getSpreadType(t, right, symbol, typeFlags, objectFlags));
return mapType(left, t => getSpreadType(t, right, symbol, typeFlags, objectFlags, isUnion));
}
if (right.flags & TypeFlags.Union) {
return mapType(right, t => getSpreadType(left, t, symbol, typeFlags, objectFlags));
return mapType(right, t => getSpreadType(left, t, symbol, typeFlags, objectFlags, true));
}
if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) {
return left;
@ -9870,6 +9870,14 @@ namespace ts {
result.nameType = leftProp.nameType;
members.set(leftProp.escapedName, result);
}
else if (strictNullChecks &&
!isUnion &&
symbol &&
shouldCheckAsExcessProperty(leftProp, symbol) &&
!shouldCheckAsExcessProperty(rightProp, symbol) &&
!(getFalsyFlags(rightType) & TypeFlags.Nullable)) {
error(leftProp.valueDeclaration, Diagnostics._0_is_overwritten_by_a_later_spread, unescapeLeadingUnderscores(leftProp.escapedName));
}
}
else {
members.set(leftProp.escapedName, getNonReadonlySymbol(leftProp));
@ -11562,7 +11570,7 @@ namespace ts {
return hasExcessProperties(source, discriminant, /*discriminant*/ undefined, reportErrors);
}
for (const prop of getPropertiesOfObjectType(source)) {
if (!isPropertyFromSpread(prop, source.symbol) && !isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) {
if (shouldCheckAsExcessProperty(prop, source.symbol) && !isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) {
if (reportErrors) {
// We know *exactly* where things went wrong when comparing the types.
// Use this property as the error node as this will be more helpful in
@ -11606,10 +11614,6 @@ namespace ts {
return false;
}
function isPropertyFromSpread(prop: Symbol, container: Symbol) {
return prop.valueDeclaration && container.valueDeclaration && prop.valueDeclaration.parent !== container.valueDeclaration;
}
function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary {
let result = Ternary.True;
const sourceTypes = source.types;
@ -12522,6 +12526,10 @@ namespace ts {
return match || defaultValue;
}
function shouldCheckAsExcessProperty(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
@ -17652,7 +17660,6 @@ namespace ts {
let spread: Type = emptyObjectType;
let hasSpreadAnyType = false;
let typeToIntersect: Type | undefined;
let explicitlySpecifyChildrenAttribute = false;
let propagatingFlags: TypeFlags = 0;
const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement));
@ -17671,9 +17678,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);
@ -17707,13 +17711,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
@ -20062,7 +20059,7 @@ namespace ts {
if (node.arguments.length === 1 && isTypeAssertion(first(node.arguments))) {
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, apparentType, SignatureKind.Call, relatedInformation);

View file

@ -2485,10 +2485,18 @@
"category": "Error",
"code": 2732
},
"It is highly likely that you are missing a semicolon.": {
"Index '{0}' is out-of-bounds in tuple of length {1}.": {
"category": "Error",
"code": 2733
},
"Are you missing a semicolon here?": {
"category": "Error",
"code": 2734
},
"'{0}' is overwritten by a later spread.": {
"category": "Error",
"code": 2735
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",

View file

@ -21,19 +21,19 @@ tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.t
(1 as number).toString();
~~~~~~~~~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:7:1: It is highly likely that you are missing a semicolon.
!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:7:1: Are you missing a semicolon here?
foo()
~~~~~~~~
(1 as number).toString();
~~~~~~~~~~~~~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:10:1: It is highly likely that you are missing a semicolon.
!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:10:1: Are you missing a semicolon here?
foo()
~~~~~~~~
(<number>1).toString();
~~~~~~~~~~~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:13:1: It is highly likely that you are missing a semicolon.
!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:13:1: Are you missing a semicolon here?

View file

@ -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<ButtonProp, any> {
render() {
// Error children are specified twice
return (<InnerButton {...this.props} children="hi">
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten.
<div>Hello World</div>
</InnerButton>);
}
}
interface InnerButtonProp {
a: number
}
class InnerButton extends React.Component<InnerButtonProp, any> {
render() {
return (<button>Hello</button>);
}
}

View file

@ -1,6 +1,5 @@
tests/cases/conformance/jsx/file.tsx(14,10): error TS2322: Type '{ a: number; b: string; }' is not assignable to type 'Prop'.
Property 'children' is missing in type '{ a: number; b: string; }'.
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 TS2322: Type '{ children: (Element | ((name: string) => Element))[]; a: number; b: string; }' is not assignable to type 'Prop'.
Types of property 'children' are incompatible.
Type '(Element | ((name: string) => Element))[]' is not assignable to type 'string | Element'.
@ -23,7 +22,7 @@ tests/cases/conformance/jsx/file.tsx(49,6): error TS2322: Type '{ children: Elem
Property 'type' is missing in type 'Element[]'.
==== tests/cases/conformance/jsx/file.tsx (6 errors) ====
==== tests/cases/conformance/jsx/file.tsx (5 errors) ====
import React = require('react');
interface Prop {
@ -44,8 +43,6 @@ tests/cases/conformance/jsx/file.tsx(49,6): error TS2322: Type '{ children: Elem
let k0 =
<Comp a={10} b="hi" children="Random" >
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten.
hi hi hi!
</Comp>;

View file

@ -1,30 +0,0 @@
tests/cases/compiler/excessPropertyCheckWithSpread.ts(6,3): error TS2345: Argument of type '{ n: number; a: number; }' is not assignable to parameter of type '{ a: any; }'.
Object literal may only specify known properties, and 'n' does not exist in type '{ a: any; }'.
tests/cases/compiler/excessPropertyCheckWithSpread.ts(16,3): error TS2345: Argument of type '{ opt: string | number; a: number; }' is not assignable to parameter of type '{ a: any; }'.
Object literal may only specify known properties, and 'opt' does not exist in type '{ a: any; }'.
==== tests/cases/compiler/excessPropertyCheckWithSpread.ts (2 errors) ====
declare function f({ a: number }): void
interface I {
readonly n: number;
}
declare let i: I;
f({ a: 1, ...i });
~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '{ n: number; a: number; }' is not assignable to parameter of type '{ a: any; }'.
!!! error TS2345: Object literal may only specify known properties, and 'n' does not exist in type '{ a: any; }'.
interface R {
opt?: number
}
interface L {
opt: string
}
declare let l: L;
declare let r: R;
f({ a: 1, ...l, ...r });
~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '{ opt: string | number; a: number; }' is not assignable to parameter of type '{ a: any; }'.
!!! error TS2345: Object literal may only specify known properties, and 'opt' does not exist in type '{ a: any; }'.

View file

@ -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 }
}
@ -138,15 +125,10 @@ var o2 = { b: 'yes', c: true };
var swap = { a: 'yes', b: -1 };
var addAfter = __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({}, o, { b: 'override' });
var nested = __assign({}, __assign({ a: 3 }, { b: false, c: 'overriden' }), { c: 'whatever' });
var combined = __assign({}, o, o2);
var combinedBefore = __assign({ b: 'ok' }, o, o2);
var combinedMid = __assign({}, o, { b: 'ok' }, o2);
var combinedAfter = __assign({}, o, o2, { b: 'ok' });
var combinedNested = __assign({}, __assign({ a: 4 }, { b: false, c: 'overriden' }), { d: 'actually new' }, { a: 5, d: 'maybe new' });
var combinedNestedChangeType = __assign({}, __assign({ a: 1 }, { b: false, c: 'overriden' }), { c: -1 });
var propertyNested = { a: __assign({}, o) };
// accessors don't copy the descriptor
@ -196,18 +178,16 @@ var cplus = __assign({}, c, { plus: function () { return this.p + 1; } });
cplus.plus();
// new field's type conflicting with existing field is OK
var changeTypeAfter = __assign({}, o, { a: 'wrong type?' });
var changeTypeBefore = __assign({ a: 'wrong type?' }, o);
var changeTypeBoth = __assign({}, o, swap);
// optional
function container(definiteBoolean, definiteString, optionalString, optionalNumber) {
var _a, _b, _c;
var _a, _b;
var optionalUnionStops = __assign({}, definiteBoolean, definiteString, optionalNumber);
var optionalUnionDuplicates = __assign({}, definiteBoolean, definiteString, optionalString, optionalNumber);
var allOptional = __assign({}, optionalString, optionalNumber);
// computed property
var computedFirst = __assign((_a = {}, _a['before everything'] = 12, _a), o, { b: 'yes' });
var computedMiddle = __assign({}, o, (_b = {}, _b['in the middle'] = 13, _b.b = 'maybe?', _b), o2);
var computedAfter = __assign({}, o, (_c = { b: 'yeah' }, _c['at the end'] = 14, _c));
var computedAfter = __assign({}, o, (_b = { b: 'yeah' }, _b['at the end'] = 14, _b));
}
// shortcut syntax
var a = 12;

View file

@ -34,179 +34,161 @@ 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<T>
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, 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, 40, 7))
...o,
>o : Symbol(o, Decl(objectSpread.ts, 40, 7))
...b && { x: 14 }
>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, 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, 40, 7))
}
function conditionalSpreadNumber(nt: number): { x: number, y: number } {
>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, 49, 7))
>x : Symbol(x, Decl(objectSpread.ts, 49, 13))
>y : Symbol(y, Decl(objectSpread.ts, 49, 20))
@ -217,28 +199,30 @@ function conditionalSpreadBoolean(b: boolean) : { x: number, y: number } {
...o,
>o : Symbol(o, Decl(objectSpread.ts, 49, 7))
...b && { x: 14 }
>b : Symbol(b, Decl(objectSpread.ts, 48, 34))
>x : Symbol(x, Decl(objectSpread.ts, 52, 17))
...nt && { x: nt }
>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 = { ...b && { x: 21 }}
let o2 = { ...nt && { x: nt }}
>o2 : Symbol(o2, Decl(objectSpread.ts, 54, 7))
>b : Symbol(b, Decl(objectSpread.ts, 48, 34))
>x : Symbol(x, Decl(objectSpread.ts, 54, 24))
>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, 49, 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))
function conditionalSpreadString(st: string): { x: string, y: number } {
>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: 15, y: 16 }
let o = { x: 'hi', y: 17 }
>o : Symbol(o, Decl(objectSpread.ts, 58, 7))
>x : Symbol(x, Decl(objectSpread.ts, 58, 13))
>y : Symbol(y, Decl(objectSpread.ts, 58, 20))
>y : Symbol(y, Decl(objectSpread.ts, 58, 22))
o = {
>o : Symbol(o, Decl(objectSpread.ts, 58, 7))
@ -246,112 +230,72 @@ function conditionalSpreadNumber(nt: number): { x: number, y: number } {
...o,
>o : Symbol(o, Decl(objectSpread.ts, 58, 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))
}
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))
return o;
>o : Symbol(o, Decl(objectSpread.ts, 58, 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))
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 = {
>o : Symbol(o, Decl(objectSpread.ts, 67, 7))
...o,
>o : Symbol(o, Decl(objectSpread.ts, 67, 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,96 +303,82 @@ 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))
>['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))
>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 }
>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 = { ...<object>{}};
>spreadNonPrimitive : Symbol(spreadNonPrimitive, Decl(objectSpread.ts, 119, 3))
>spreadNonPrimitive : Symbol(spreadNonPrimitive, Decl(objectSpread.ts, 106, 3))

View file

@ -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

View file

@ -5,19 +5,19 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(23,1): error TS2322
Property 'b' is missing in type '{ s: string; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(25,1): error TS2322: Type '{ b: boolean; }' is not assignable to type '{ s: string; b: boolean; }'.
Property 's' is missing in type '{ b: boolean; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(28,36): error TS2300: Duplicate identifier 'b'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(28,53): error TS2300: Duplicate identifier 'b'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(32,19): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(33,19): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(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: Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(47,12): error TS2339: Property 'b' does not exist on type '{}'.
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(62,14): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(65,14): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(27,36): error TS2300: Duplicate identifier 'b'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(27,53): error TS2300: Duplicate identifier 'b'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(47,19): error TS2698: Spread types may only be created from object types.
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,20): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(51,20): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(53,19): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(58,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(62,12): error TS2339: Property 'b' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(68,9): error TS2339: Property 'm' does not exist on type '{ p: number; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(73,11): error TS2339: Property 'a' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(77,14): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(80,14): error TS2698: Spread types may only be created from object types.
==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (17 errors) ====
@ -58,13 +58,28 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(65,14): error TS269
!!! error TS2322: Type '{ b: boolean; }' is not assignable to type '{ s: string; b: boolean; }'.
!!! error TS2322: Property 's' is missing in type '{ b: boolean; }'.
// literal repeats are not allowed, but spread repeats are fine
let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' }
~
!!! 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 }
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 };

View file

@ -25,9 +25,24 @@ spread = { s: "foo" }; // error, missing 'b'
let b = { b: false };
spread = b; // error, missing 's'
// literal repeats are not allowed, but spread repeats are fine
let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' }
let duplicatedSpread = { ...o, ...o }
// 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 };
@ -87,6 +102,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 () {
@ -112,9 +128,17 @@ var spread = __assign({ b: true }, { s: "foo" });
spread = { s: "foo" }; // error, missing 'b'
var b = { b: false };
spread = b; // error, missing 's'
// literal repeats are not allowed, but spread repeats are fine
var duplicated = __assign({ b: 'bad' }, o, { b: 'bad' }, o2, { b: 'bad' });
var duplicatedSpread = __assign({}, o, o);
// 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({ b: 'ok' }, o3, o4);
var combinedMid = __assign({}, o3, { b: 'ok' }, o4);
var combinedNested = __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({}, 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);

View file

@ -76,170 +76,249 @@ spread = b; // error, missing 's'
>spread : Symbol(spread, Decl(objectSpreadNegative.ts, 21, 3))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 23, 3))
// literal repeats are not allowed, but spread repeats are fine
let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' }
>duplicated : Symbol(duplicated, Decl(objectSpreadNegative.ts, 27, 3))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 27, 18), Decl(objectSpreadNegative.ts, 27, 34), Decl(objectSpreadNegative.ts, 27, 51))
>duplicated : Symbol(duplicated, Decl(objectSpreadNegative.ts, 26, 3))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 26, 18), Decl(objectSpreadNegative.ts, 26, 34), Decl(objectSpreadNegative.ts, 26, 51))
>o : Symbol(o, Decl(objectSpreadNegative.ts, 0, 3))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 27, 18), Decl(objectSpreadNegative.ts, 27, 34), Decl(objectSpreadNegative.ts, 27, 51))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 26, 18), Decl(objectSpreadNegative.ts, 26, 34), Decl(objectSpreadNegative.ts, 26, 51))
>o2 : Symbol(o2, Decl(objectSpreadNegative.ts, 11, 3))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 27, 18), Decl(objectSpreadNegative.ts, 27, 34), Decl(objectSpreadNegative.ts, 27, 51))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 26, 18), Decl(objectSpreadNegative.ts, 26, 34), Decl(objectSpreadNegative.ts, 26, 51))
let duplicatedSpread = { ...o, ...o }
>duplicatedSpread : Symbol(duplicatedSpread, Decl(objectSpreadNegative.ts, 28, 3))
>duplicatedSpread : Symbol(duplicatedSpread, Decl(objectSpreadNegative.ts, 27, 3))
>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, 29, 3))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 29, 13))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 29, 24))
{ b: 'ignored', ...o }
>b : Symbol(b, Decl(objectSpreadNegative.ts, 30, 5))
>o : Symbol(o, Decl(objectSpreadNegative.ts, 0, 3))
let o3 = { a: 1, b: 'no' }
>o3 : Symbol(o3, Decl(objectSpreadNegative.ts, 32, 3))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 32, 10))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 32, 16))
let o4 = { b: 'yes', c: true }
>o4 : Symbol(o4, Decl(objectSpreadNegative.ts, 33, 3))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 33, 10))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 33, 20))
let combinedBefore: { a: number, b: string, c: boolean } =
>combinedBefore : Symbol(combinedBefore, Decl(objectSpreadNegative.ts, 34, 3))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 34, 21))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 34, 32))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 34, 43))
{ b: 'ok', ...o3, ...o4 }
>b : Symbol(b, Decl(objectSpreadNegative.ts, 35, 5))
>o3 : Symbol(o3, Decl(objectSpreadNegative.ts, 32, 3))
>o4 : Symbol(o4, Decl(objectSpreadNegative.ts, 33, 3))
let combinedMid: { a: number, b: string, c: boolean } =
>combinedMid : Symbol(combinedMid, Decl(objectSpreadNegative.ts, 36, 3))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 36, 18))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 36, 29))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 36, 40))
{ ...o3, b: 'ok', ...o4 }
>o3 : Symbol(o3, Decl(objectSpreadNegative.ts, 32, 3))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 37, 12))
>o4 : Symbol(o4, Decl(objectSpreadNegative.ts, 33, 3))
let combinedNested: { a: number, b: boolean, c: string, d: string } =
>combinedNested : Symbol(combinedNested, Decl(objectSpreadNegative.ts, 38, 3))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 38, 21))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 38, 32))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 38, 44))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 38, 55))
{ ...{ a: 4, ...{ b: false, c: 'overriden' } }, d: 'actually new', ...{ a: 5, d: 'maybe new' } }
>a : Symbol(a, Decl(objectSpreadNegative.ts, 39, 10))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 39, 21))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 39, 31))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 39, 51))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 39, 75))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 39, 81))
let changeTypeBefore: { a: number, b: string } =
>changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpreadNegative.ts, 40, 3))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 40, 23))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 40, 34))
{ a: 'wrong type?', ...o3 };
>a : Symbol(a, Decl(objectSpreadNegative.ts, 41, 5))
>o3 : Symbol(o3, Decl(objectSpreadNegative.ts, 32, 3))
let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } =
>computedMiddle : Symbol(computedMiddle, Decl(objectSpreadNegative.ts, 42, 3))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 42, 21))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 42, 32))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 42, 43))
>"in the middle" : Symbol("in the middle", Decl(objectSpreadNegative.ts, 42, 55))
{ ...o3, ['in the middle']: 13, b: 'maybe?', ...o4 }
>o3 : Symbol(o3, Decl(objectSpreadNegative.ts, 32, 3))
>['in the middle'] : Symbol(['in the middle'], Decl(objectSpreadNegative.ts, 43, 12))
>'in the middle' : Symbol(['in the middle'], Decl(objectSpreadNegative.ts, 43, 12))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 43, 35))
>o4 : Symbol(o4, Decl(objectSpreadNegative.ts, 33, 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, 46, 3))
let spreadSum = { ...1 + 1 };
>spreadSum : Symbol(spreadSum, Decl(objectSpreadNegative.ts, 32, 3))
>spreadSum : Symbol(spreadSum, Decl(objectSpreadNegative.ts, 47, 3))
let spreadZero = { ...0 };
>spreadZero : Symbol(spreadZero, Decl(objectSpreadNegative.ts, 33, 3))
>spreadZero : Symbol(spreadZero, Decl(objectSpreadNegative.ts, 48, 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, 48, 3))
let spreadBool = { ...true };
>spreadBool : Symbol(spreadBool, Decl(objectSpreadNegative.ts, 35, 3))
>spreadBool : Symbol(spreadBool, Decl(objectSpreadNegative.ts, 50, 3))
spreadBool.valueOf();
>spreadBool : Symbol(spreadBool, Decl(objectSpreadNegative.ts, 35, 3))
>spreadBool : Symbol(spreadBool, Decl(objectSpreadNegative.ts, 50, 3))
let spreadStr = { ...'foo' };
>spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 37, 3))
>spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 52, 3))
spreadStr.length; // error, no 'length'
>spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 37, 3))
>spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 52, 3))
spreadStr.charAt(1); // error, no methods either
>spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 37, 3))
>spreadStr : Symbol(spreadStr, Decl(objectSpreadNegative.ts, 52, 3))
// functions are skipped
let spreadFunc = { ...function () { } }
>spreadFunc : Symbol(spreadFunc, Decl(objectSpreadNegative.ts, 41, 3))
>spreadFunc : Symbol(spreadFunc, Decl(objectSpreadNegative.ts, 56, 3))
spreadFunc(); // error, no call signature
>spreadFunc : Symbol(spreadFunc, Decl(objectSpreadNegative.ts, 41, 3))
>spreadFunc : Symbol(spreadFunc, Decl(objectSpreadNegative.ts, 56, 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, 60, 3))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 60, 23))
>bad : Symbol(bad, Decl(objectSpreadNegative.ts, 60, 31))
setterOnly.b = 12; // error, 'b' does not exist
>setterOnly : Symbol(setterOnly, Decl(objectSpreadNegative.ts, 45, 3))
>setterOnly : Symbol(setterOnly, Decl(objectSpreadNegative.ts, 60, 3))
// 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, 61, 18))
>p : Symbol(C.p, Decl(objectSpreadNegative.ts, 64, 9))
>m : Symbol(C.m, Decl(objectSpreadNegative.ts, 64, 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, 65, 3))
>C : Symbol(C, Decl(objectSpreadNegative.ts, 61, 18))
>C : Symbol(C, Decl(objectSpreadNegative.ts, 61, 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, 66, 3))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 65, 3))
spreadC.m(); // error 'm' is not in '{ ... c }'
>spreadC : Symbol(spreadC, Decl(objectSpreadNegative.ts, 51, 3))
>spreadC : Symbol(spreadC, Decl(objectSpreadNegative.ts, 66, 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, 70, 3))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 70, 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, 71, 3))
>obj : Symbol(obj, Decl(objectSpreadNegative.ts, 70, 3))
spreadObj.a; // error 'a' is not in {}
>spreadObj : Symbol(spreadObj, Decl(objectSpreadNegative.ts, 56, 3))
>spreadObj : Symbol(spreadObj, Decl(objectSpreadNegative.ts, 71, 3))
// generics
function f<T, U>(t: T, u: U) {
>f : Symbol(f, Decl(objectSpreadNegative.ts, 57, 12))
>T : Symbol(T, Decl(objectSpreadNegative.ts, 60, 11))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 60, 13))
>t : Symbol(t, Decl(objectSpreadNegative.ts, 60, 17))
>T : Symbol(T, Decl(objectSpreadNegative.ts, 60, 11))
>u : Symbol(u, Decl(objectSpreadNegative.ts, 60, 22))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 60, 13))
>f : Symbol(f, Decl(objectSpreadNegative.ts, 72, 12))
>T : Symbol(T, Decl(objectSpreadNegative.ts, 75, 11))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 75, 13))
>t : Symbol(t, Decl(objectSpreadNegative.ts, 75, 17))
>T : Symbol(T, Decl(objectSpreadNegative.ts, 75, 11))
>u : Symbol(u, Decl(objectSpreadNegative.ts, 75, 22))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 75, 13))
return { ...t, ...u, id: 'id' };
>t : Symbol(t, Decl(objectSpreadNegative.ts, 60, 17))
>u : Symbol(u, Decl(objectSpreadNegative.ts, 60, 22))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 61, 24))
>t : Symbol(t, Decl(objectSpreadNegative.ts, 75, 17))
>u : Symbol(u, Decl(objectSpreadNegative.ts, 75, 22))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 76, 24))
}
function override<U>(initial: U, override: U): U {
>override : Symbol(override, Decl(objectSpreadNegative.ts, 62, 1))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 63, 18))
>initial : Symbol(initial, Decl(objectSpreadNegative.ts, 63, 21))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 63, 18))
>override : Symbol(override, Decl(objectSpreadNegative.ts, 63, 32))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 63, 18))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 63, 18))
>override : Symbol(override, Decl(objectSpreadNegative.ts, 77, 1))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 78, 18))
>initial : Symbol(initial, Decl(objectSpreadNegative.ts, 78, 21))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 78, 18))
>override : Symbol(override, Decl(objectSpreadNegative.ts, 78, 32))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 78, 18))
>U : Symbol(U, Decl(objectSpreadNegative.ts, 78, 18))
return { ...initial, ...override };
>initial : Symbol(initial, Decl(objectSpreadNegative.ts, 63, 21))
>override : Symbol(override, Decl(objectSpreadNegative.ts, 63, 32))
>initial : Symbol(initial, Decl(objectSpreadNegative.ts, 78, 21))
>override : Symbol(override, Decl(objectSpreadNegative.ts, 78, 32))
}
let exclusive: { id: string, a: number, b: string, c: string, d: boolean } =
>exclusive : Symbol(exclusive, Decl(objectSpreadNegative.ts, 66, 3))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 66, 16))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 66, 28))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 66, 39))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 66, 50))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 66, 61))
>exclusive : Symbol(exclusive, Decl(objectSpreadNegative.ts, 81, 3))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 81, 16))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 81, 28))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 81, 39))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 81, 50))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 81, 61))
f({ a: 1, b: 'yes' }, { c: 'no', d: false })
>f : Symbol(f, Decl(objectSpreadNegative.ts, 57, 12))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 67, 7))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 67, 13))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 67, 27))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 67, 36))
>f : Symbol(f, Decl(objectSpreadNegative.ts, 72, 12))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 82, 7))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 82, 13))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 82, 27))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 82, 36))
let overlap: { id: string, a: number, b: string } =
>overlap : Symbol(overlap, Decl(objectSpreadNegative.ts, 68, 3))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 68, 14))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 68, 26))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 68, 37))
>overlap : Symbol(overlap, Decl(objectSpreadNegative.ts, 83, 3))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 83, 14))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 83, 26))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 83, 37))
f({ a: 1 }, { a: 2, b: 'extra' })
>f : Symbol(f, Decl(objectSpreadNegative.ts, 57, 12))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 69, 7))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 69, 17))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 69, 23))
>f : Symbol(f, Decl(objectSpreadNegative.ts, 72, 12))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 84, 7))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 84, 17))
>b : Symbol(b, Decl(objectSpreadNegative.ts, 84, 23))
let overlapConflict: { id:string, a: string } =
>overlapConflict : Symbol(overlapConflict, Decl(objectSpreadNegative.ts, 70, 3))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 70, 22))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 70, 33))
>overlapConflict : Symbol(overlapConflict, Decl(objectSpreadNegative.ts, 85, 3))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 85, 22))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 85, 33))
f({ a: 1 }, { a: 'mismatch' })
>f : Symbol(f, Decl(objectSpreadNegative.ts, 57, 12))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 71, 7))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 71, 17))
>f : Symbol(f, Decl(objectSpreadNegative.ts, 72, 12))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 86, 7))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 86, 17))
let overwriteId: { id: string, a: number, c: number, d: string } =
>overwriteId : Symbol(overwriteId, Decl(objectSpreadNegative.ts, 72, 3))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 72, 18))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 72, 30))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 72, 41))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 72, 52))
>overwriteId : Symbol(overwriteId, Decl(objectSpreadNegative.ts, 87, 3))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 87, 18))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 87, 30))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 87, 41))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 87, 52))
f({ a: 1, id: true }, { c: 1, d: 'no' })
>f : Symbol(f, Decl(objectSpreadNegative.ts, 57, 12))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 73, 7))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 73, 13))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 73, 27))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 73, 33))
>f : Symbol(f, Decl(objectSpreadNegative.ts, 72, 12))
>a : Symbol(a, Decl(objectSpreadNegative.ts, 88, 7))
>id : Symbol(id, Decl(objectSpreadNegative.ts, 88, 13))
>c : Symbol(c, Decl(objectSpreadNegative.ts, 88, 27))
>d : Symbol(d, Decl(objectSpreadNegative.ts, 88, 33))

View file

@ -90,7 +90,6 @@ spread = b; // error, missing 's'
>spread : { s: string; b: boolean; }
>b : { b: boolean; }
// literal repeats are not allowed, but spread repeats are fine
let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' }
>duplicated : { b: string; a: number; }
>{ b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' } : { b: string; a: number; }
@ -109,6 +108,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

View file

@ -0,0 +1,36 @@
//// [spreadOverwritesProperty.ts]
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
}
//// [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({}, ab, ab);
var unused3 = __assign({ b: 1 }, abq);
function g(obj) {
return __assign({ x: 1 }, obj); // should be allowed because of undefined
}
function h(obj) {
return __assign({ x: 1 }, obj); // should be allowed because we don't know about undefined
}

View file

@ -0,0 +1,45 @@
=== tests/cases/conformance/types/spread/spreadOverwritesProperty.ts ===
declare var ab: { a: number, b: number };
>ab : Symbol(ab, Decl(spreadOverwritesProperty.ts, 0, 11))
>a : Symbol(a, Decl(spreadOverwritesProperty.ts, 0, 17))
>b : Symbol(b, Decl(spreadOverwritesProperty.ts, 0, 28))
declare var abq: { a: number, b?: number };
>abq : Symbol(abq, Decl(spreadOverwritesProperty.ts, 1, 11))
>a : Symbol(a, Decl(spreadOverwritesProperty.ts, 1, 18))
>b : Symbol(b, Decl(spreadOverwritesProperty.ts, 1, 29))
var unused1 = { b: 1, ...ab }
>unused1 : Symbol(unused1, Decl(spreadOverwritesProperty.ts, 2, 3))
>b : Symbol(b, Decl(spreadOverwritesProperty.ts, 2, 15))
>ab : Symbol(ab, Decl(spreadOverwritesProperty.ts, 0, 11))
var unused2 = { ...ab, ...ab }
>unused2 : Symbol(unused2, Decl(spreadOverwritesProperty.ts, 3, 3))
>ab : Symbol(ab, Decl(spreadOverwritesProperty.ts, 0, 11))
>ab : Symbol(ab, Decl(spreadOverwritesProperty.ts, 0, 11))
var unused3 = { b: 1, ...abq }
>unused3 : Symbol(unused3, Decl(spreadOverwritesProperty.ts, 4, 3))
>b : Symbol(b, Decl(spreadOverwritesProperty.ts, 4, 15))
>abq : Symbol(abq, Decl(spreadOverwritesProperty.ts, 1, 11))
function g(obj: { x: number | undefined }) {
>g : Symbol(g, Decl(spreadOverwritesProperty.ts, 4, 30))
>obj : Symbol(obj, Decl(spreadOverwritesProperty.ts, 6, 11))
>x : Symbol(x, Decl(spreadOverwritesProperty.ts, 6, 17))
return { x: 1, ...obj }; // should be allowed because of undefined
>x : Symbol(x, Decl(spreadOverwritesProperty.ts, 7, 12))
>obj : Symbol(obj, Decl(spreadOverwritesProperty.ts, 6, 11))
}
function h(obj: { x: number }) {
>h : Symbol(h, Decl(spreadOverwritesProperty.ts, 8, 1))
>obj : Symbol(obj, Decl(spreadOverwritesProperty.ts, 9, 11))
>x : Symbol(x, Decl(spreadOverwritesProperty.ts, 9, 17))
return { x: 1, ...obj }; // should be allowed because we don't know about undefined
>x : Symbol(x, Decl(spreadOverwritesProperty.ts, 10, 12))
>obj : Symbol(obj, Decl(spreadOverwritesProperty.ts, 9, 11))
}

View file

@ -0,0 +1,54 @@
=== tests/cases/conformance/types/spread/spreadOverwritesProperty.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; }
>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 }; // should be allowed because of undefined
>{ 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 }; // should be allowed because we don't know about undefined
>{ x: 1, ...obj } : { x: number; }
>x : number
>1 : 1
>obj : { x: number; }
}

View file

@ -0,0 +1,18 @@
tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(3,17): error TS2735: 'b' is overwritten by a later spread.
==== tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts (1 errors) ====
declare var ab: { a: number, b: number };
declare var abq: { a: number, b?: number };
var unused1 = { b: 1, ...ab }
~~~~
!!! error TS2735: 'b' is overwritten by a later spread.
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 };
}

View file

@ -0,0 +1,36 @@
//// [spreadOverwritesPropertyStrict.ts]
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 };
}
//// [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);
var unused2 = __assign({}, ab, ab);
var unused3 = __assign({ b: 1 }, abq);
function g(obj) {
return __assign({ x: 1 }, obj); // should be allowed because of undefined
}
function f(obj) {
return __assign({ x: 1 }, obj);
}

View file

@ -0,0 +1,45 @@
=== 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 }
>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 }
>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 }
>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 }; // should be allowed because of 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 };
>x : Symbol(x, Decl(spreadOverwritesPropertyStrict.ts, 9, 12))
>obj : Symbol(obj, Decl(spreadOverwritesPropertyStrict.ts, 8, 11))
}

View file

@ -0,0 +1,54 @@
=== 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 }
>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 | 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 }; // should be allowed because of 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; } | { x: number; }
>obj : { x: number; } | undefined
>x : number
return { x: 1, ...obj };
>{ x: 1, ...obj } : { x: number; } | { x: number; }
>x : number
>1 : 1
>obj : { x: number; } | undefined
}

View file

@ -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 }
}

View file

@ -25,9 +25,24 @@ spread = { s: "foo" }; // error, missing 'b'
let b = { b: false };
spread = b; // error, missing 's'
// literal repeats are not allowed, but spread repeats are fine
let duplicated = { b: 'bad', ...o, b: 'bad', ...o2, b: 'bad' }
let duplicatedSpread = { ...o, ...o }
// 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 };

View file

@ -0,0 +1,12 @@
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
}

View file

@ -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 };
}