No excess property error for spread properties (#26798)
That is, properties in an object literal type that came from a spread assignment never cause an excess property error.
This commit is contained in:
parent
cd37e41d3d
commit
b687caf3eb
|
@ -11328,7 +11328,7 @@ namespace ts {
|
|||
return hasExcessProperties(source, discriminant, /*discriminant*/ undefined, reportErrors);
|
||||
}
|
||||
for (const prop of getPropertiesOfObjectType(source)) {
|
||||
if (!isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) {
|
||||
if (!isPropertyFromSpread(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
|
||||
|
@ -11372,6 +11372,10 @@ 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;
|
||||
|
|
|
@ -18,15 +18,9 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(53,9): error TS2339
|
|||
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(79,37): error TS2322: Type '{ a: string; b: string; extra: string; }' is not assignable to type 'A'.
|
||||
Object literal may only specify known properties, and 'extra' does not exist in type 'A'.
|
||||
tests/cases/conformance/types/spread/objectSpreadNegative.ts(82,7): error TS2322: Type '{ a: string; b: string; extra: string; }' is not assignable to type 'A'.
|
||||
Object literal may only specify known properties, and 'extra' does not exist in type 'A'.
|
||||
tests/cases/conformance/types/spread/objectSpreadNegative.ts(84,7): error TS2322: Type '{ a: string; b: string; extra: string; }' is not assignable to type 'A'.
|
||||
Object literal may only specify known properties, and 'extra' does not exist in type 'A'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (20 errors) ====
|
||||
==== tests/cases/conformance/types/spread/objectSpreadNegative.ts (17 errors) ====
|
||||
let o = { a: 1, b: 'no' }
|
||||
|
||||
/// private propagates
|
||||
|
@ -138,23 +132,4 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(84,7): error TS2322
|
|||
f({ a: 1 }, { a: 'mismatch' })
|
||||
let overwriteId: { id: string, a: number, c: number, d: string } =
|
||||
f({ a: 1, id: true }, { c: 1, d: 'no' })
|
||||
|
||||
// excess property checks
|
||||
type A = { a: string, b: string };
|
||||
type Extra = { a: string, b: string, extra: string };
|
||||
const extra1: A = { a: "a", b: "b", extra: "extra" };
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ a: string; b: string; extra: string; }' is not assignable to type 'A'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'extra' does not exist in type 'A'.
|
||||
const extra2 = { a: "a", b: "b", extra: "extra" };
|
||||
const a1: A = { ...extra1 }; // error spans should be here
|
||||
const a2: A = { ...extra2 }; // not on the symbol declarations above
|
||||
~~
|
||||
!!! error TS2322: Type '{ a: string; b: string; extra: string; }' is not assignable to type 'A'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'extra' does not exist in type 'A'.
|
||||
const extra3: Extra = { a: "a", b: "b", extra: "extra" };
|
||||
const a3: A = { ...extra3 }; // same here
|
||||
~~
|
||||
!!! error TS2322: Type '{ a: string; b: string; extra: string; }' is not assignable to type 'A'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'extra' does not exist in type 'A'.
|
||||
|
|
@ -73,16 +73,6 @@ let overlapConflict: { id:string, a: string } =
|
|||
f({ a: 1 }, { a: 'mismatch' })
|
||||
let overwriteId: { id: string, a: number, c: number, d: string } =
|
||||
f({ a: 1, id: true }, { c: 1, d: 'no' })
|
||||
|
||||
// excess property checks
|
||||
type A = { a: string, b: string };
|
||||
type Extra = { a: string, b: string, extra: string };
|
||||
const extra1: A = { a: "a", b: "b", extra: "extra" };
|
||||
const extra2 = { a: "a", b: "b", extra: "extra" };
|
||||
const a1: A = { ...extra1 }; // error spans should be here
|
||||
const a2: A = { ...extra2 }; // not on the symbol declarations above
|
||||
const extra3: Extra = { a: "a", b: "b", extra: "extra" };
|
||||
const a3: A = { ...extra3 }; // same here
|
||||
|
||||
|
||||
//// [objectSpreadNegative.js]
|
||||
|
@ -167,9 +157,3 @@ var exclusive = f({ a: 1, b: 'yes' }, { c: 'no', d: false });
|
|||
var overlap = f({ a: 1 }, { a: 2, b: 'extra' });
|
||||
var overlapConflict = f({ a: 1 }, { a: 'mismatch' });
|
||||
var overwriteId = f({ a: 1, id: true }, { c: 1, d: 'no' });
|
||||
var extra1 = { a: "a", b: "b", extra: "extra" };
|
||||
var extra2 = { a: "a", b: "b", extra: "extra" };
|
||||
var a1 = __assign({}, extra1); // error spans should be here
|
||||
var a2 = __assign({}, extra2); // not on the symbol declarations above
|
||||
var extra3 = { a: "a", b: "b", extra: "extra" };
|
||||
var a3 = __assign({}, extra3); // same here
|
||||
|
|
|
@ -243,50 +243,3 @@ let overwriteId: { id: string, a: number, c: number, d: string } =
|
|||
>c : Symbol(c, Decl(objectSpreadNegative.ts, 73, 27))
|
||||
>d : Symbol(d, Decl(objectSpreadNegative.ts, 73, 33))
|
||||
|
||||
// excess property checks
|
||||
type A = { a: string, b: string };
|
||||
>A : Symbol(A, Decl(objectSpreadNegative.ts, 73, 44))
|
||||
>a : Symbol(a, Decl(objectSpreadNegative.ts, 76, 10))
|
||||
>b : Symbol(b, Decl(objectSpreadNegative.ts, 76, 21))
|
||||
|
||||
type Extra = { a: string, b: string, extra: string };
|
||||
>Extra : Symbol(Extra, Decl(objectSpreadNegative.ts, 76, 34))
|
||||
>a : Symbol(a, Decl(objectSpreadNegative.ts, 77, 14))
|
||||
>b : Symbol(b, Decl(objectSpreadNegative.ts, 77, 25))
|
||||
>extra : Symbol(extra, Decl(objectSpreadNegative.ts, 77, 36))
|
||||
|
||||
const extra1: A = { a: "a", b: "b", extra: "extra" };
|
||||
>extra1 : Symbol(extra1, Decl(objectSpreadNegative.ts, 78, 5))
|
||||
>A : Symbol(A, Decl(objectSpreadNegative.ts, 73, 44))
|
||||
>a : Symbol(a, Decl(objectSpreadNegative.ts, 78, 19))
|
||||
>b : Symbol(b, Decl(objectSpreadNegative.ts, 78, 27))
|
||||
>extra : Symbol(extra, Decl(objectSpreadNegative.ts, 78, 35))
|
||||
|
||||
const extra2 = { a: "a", b: "b", extra: "extra" };
|
||||
>extra2 : Symbol(extra2, Decl(objectSpreadNegative.ts, 79, 5))
|
||||
>a : Symbol(a, Decl(objectSpreadNegative.ts, 79, 16))
|
||||
>b : Symbol(b, Decl(objectSpreadNegative.ts, 79, 24))
|
||||
>extra : Symbol(extra, Decl(objectSpreadNegative.ts, 79, 32))
|
||||
|
||||
const a1: A = { ...extra1 }; // error spans should be here
|
||||
>a1 : Symbol(a1, Decl(objectSpreadNegative.ts, 80, 5))
|
||||
>A : Symbol(A, Decl(objectSpreadNegative.ts, 73, 44))
|
||||
>extra1 : Symbol(extra1, Decl(objectSpreadNegative.ts, 78, 5))
|
||||
|
||||
const a2: A = { ...extra2 }; // not on the symbol declarations above
|
||||
>a2 : Symbol(a2, Decl(objectSpreadNegative.ts, 81, 5))
|
||||
>A : Symbol(A, Decl(objectSpreadNegative.ts, 73, 44))
|
||||
>extra2 : Symbol(extra2, Decl(objectSpreadNegative.ts, 79, 5))
|
||||
|
||||
const extra3: Extra = { a: "a", b: "b", extra: "extra" };
|
||||
>extra3 : Symbol(extra3, Decl(objectSpreadNegative.ts, 82, 5))
|
||||
>Extra : Symbol(Extra, Decl(objectSpreadNegative.ts, 76, 34))
|
||||
>a : Symbol(a, Decl(objectSpreadNegative.ts, 82, 23))
|
||||
>b : Symbol(b, Decl(objectSpreadNegative.ts, 82, 31))
|
||||
>extra : Symbol(extra, Decl(objectSpreadNegative.ts, 82, 39))
|
||||
|
||||
const a3: A = { ...extra3 }; // same here
|
||||
>a3 : Symbol(a3, Decl(objectSpreadNegative.ts, 83, 5))
|
||||
>A : Symbol(A, Decl(objectSpreadNegative.ts, 73, 44))
|
||||
>extra3 : Symbol(extra3, Decl(objectSpreadNegative.ts, 82, 5))
|
||||
|
||||
|
|
|
@ -325,60 +325,3 @@ let overwriteId: { id: string, a: number, c: number, d: string } =
|
|||
>d : string
|
||||
>'no' : "no"
|
||||
|
||||
// excess property checks
|
||||
type A = { a: string, b: string };
|
||||
>A : A
|
||||
>a : string
|
||||
>b : string
|
||||
|
||||
type Extra = { a: string, b: string, extra: string };
|
||||
>Extra : Extra
|
||||
>a : string
|
||||
>b : string
|
||||
>extra : string
|
||||
|
||||
const extra1: A = { a: "a", b: "b", extra: "extra" };
|
||||
>extra1 : A
|
||||
>{ a: "a", b: "b", extra: "extra" } : { a: string; b: string; extra: string; }
|
||||
>a : string
|
||||
>"a" : "a"
|
||||
>b : string
|
||||
>"b" : "b"
|
||||
>extra : string
|
||||
>"extra" : "extra"
|
||||
|
||||
const extra2 = { a: "a", b: "b", extra: "extra" };
|
||||
>extra2 : { a: string; b: string; extra: string; }
|
||||
>{ a: "a", b: "b", extra: "extra" } : { a: string; b: string; extra: string; }
|
||||
>a : string
|
||||
>"a" : "a"
|
||||
>b : string
|
||||
>"b" : "b"
|
||||
>extra : string
|
||||
>"extra" : "extra"
|
||||
|
||||
const a1: A = { ...extra1 }; // error spans should be here
|
||||
>a1 : A
|
||||
>{ ...extra1 } : { a: string; b: string; }
|
||||
>extra1 : A
|
||||
|
||||
const a2: A = { ...extra2 }; // not on the symbol declarations above
|
||||
>a2 : A
|
||||
>{ ...extra2 } : { a: string; b: string; extra: string; }
|
||||
>extra2 : { a: string; b: string; extra: string; }
|
||||
|
||||
const extra3: Extra = { a: "a", b: "b", extra: "extra" };
|
||||
>extra3 : Extra
|
||||
>{ a: "a", b: "b", extra: "extra" } : { a: string; b: string; extra: string; }
|
||||
>a : string
|
||||
>"a" : "a"
|
||||
>b : string
|
||||
>"b" : "b"
|
||||
>extra : string
|
||||
>"extra" : "extra"
|
||||
|
||||
const a3: A = { ...extra3 }; // same here
|
||||
>a3 : A
|
||||
>{ ...extra3 } : { a: string; b: string; extra: string; }
|
||||
>extra3 : Extra
|
||||
|
||||
|
|
20
tests/baselines/reference/spreadExcessProperty.js
Normal file
20
tests/baselines/reference/spreadExcessProperty.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
//// [spreadExcessProperty.ts]
|
||||
type A = { a: string, b: string };
|
||||
const extra1 = { a: "a", b: "b", extra: "extra" };
|
||||
const a1: A = { ...extra1 }; // spread should not give excess property errors
|
||||
|
||||
|
||||
//// [spreadExcessProperty.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 extra1 = { a: "a", b: "b", extra: "extra" };
|
||||
var a1 = __assign({}, extra1); // spread should not give excess property errors
|
17
tests/baselines/reference/spreadExcessProperty.symbols
Normal file
17
tests/baselines/reference/spreadExcessProperty.symbols
Normal file
|
@ -0,0 +1,17 @@
|
|||
=== tests/cases/conformance/types/spread/spreadExcessProperty.ts ===
|
||||
type A = { a: string, b: string };
|
||||
>A : Symbol(A, Decl(spreadExcessProperty.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(spreadExcessProperty.ts, 0, 10))
|
||||
>b : Symbol(b, Decl(spreadExcessProperty.ts, 0, 21))
|
||||
|
||||
const extra1 = { a: "a", b: "b", extra: "extra" };
|
||||
>extra1 : Symbol(extra1, Decl(spreadExcessProperty.ts, 1, 5))
|
||||
>a : Symbol(a, Decl(spreadExcessProperty.ts, 1, 16))
|
||||
>b : Symbol(b, Decl(spreadExcessProperty.ts, 1, 24))
|
||||
>extra : Symbol(extra, Decl(spreadExcessProperty.ts, 1, 32))
|
||||
|
||||
const a1: A = { ...extra1 }; // spread should not give excess property errors
|
||||
>a1 : Symbol(a1, Decl(spreadExcessProperty.ts, 2, 5))
|
||||
>A : Symbol(A, Decl(spreadExcessProperty.ts, 0, 0))
|
||||
>extra1 : Symbol(extra1, Decl(spreadExcessProperty.ts, 1, 5))
|
||||
|
21
tests/baselines/reference/spreadExcessProperty.types
Normal file
21
tests/baselines/reference/spreadExcessProperty.types
Normal file
|
@ -0,0 +1,21 @@
|
|||
=== tests/cases/conformance/types/spread/spreadExcessProperty.ts ===
|
||||
type A = { a: string, b: string };
|
||||
>A : A
|
||||
>a : string
|
||||
>b : string
|
||||
|
||||
const extra1 = { a: "a", b: "b", extra: "extra" };
|
||||
>extra1 : { a: string; b: string; extra: string; }
|
||||
>{ a: "a", b: "b", extra: "extra" } : { a: string; b: string; extra: string; }
|
||||
>a : string
|
||||
>"a" : "a"
|
||||
>b : string
|
||||
>"b" : "b"
|
||||
>extra : string
|
||||
>"extra" : "extra"
|
||||
|
||||
const a1: A = { ...extra1 }; // spread should not give excess property errors
|
||||
>a1 : A
|
||||
>{ ...extra1 } : { a: string; b: string; extra: string; }
|
||||
>extra1 : { a: string; b: string; extra: string; }
|
||||
|
|
@ -73,13 +73,3 @@ let overlapConflict: { id:string, a: string } =
|
|||
f({ a: 1 }, { a: 'mismatch' })
|
||||
let overwriteId: { id: string, a: number, c: number, d: string } =
|
||||
f({ a: 1, id: true }, { c: 1, d: 'no' })
|
||||
|
||||
// excess property checks
|
||||
type A = { a: string, b: string };
|
||||
type Extra = { a: string, b: string, extra: string };
|
||||
const extra1: A = { a: "a", b: "b", extra: "extra" };
|
||||
const extra2 = { a: "a", b: "b", extra: "extra" };
|
||||
const a1: A = { ...extra1 }; // error spans should be here
|
||||
const a2: A = { ...extra2 }; // not on the symbol declarations above
|
||||
const extra3: Extra = { a: "a", b: "b", extra: "extra" };
|
||||
const a3: A = { ...extra3 }; // same here
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
type A = { a: string, b: string };
|
||||
const extra1 = { a: "a", b: "b", extra: "extra" };
|
||||
const a1: A = { ...extra1 }; // spread should not give excess property errors
|
Loading…
Reference in a new issue