Skip to content

Commit 487504d

Browse files
authored
Merge pull request #19250 from Microsoft/mark-fresh-spread-types-with-ContainsObjectLiteral
Mark fresh spread types with ContainsObjectLiteral
2 parents f09fe3d + e58aa10 commit 487504d

7 files changed

+84
-2
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7972,7 +7972,7 @@ namespace ts {
79727972

79737973
const spread = createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
79747974
spread.flags |= propagatedFlags;
7975-
spread.flags |= TypeFlags.FreshLiteral;
7975+
spread.flags |= TypeFlags.FreshLiteral | TypeFlags.ContainsObjectLiteral;
79767976
(spread as ObjectType).objectFlags |= ObjectFlags.ObjectLiteral;
79777977
spread.symbol = symbol;
79787978
return spread;

tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,10 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(40,1): error TS2322: Type
9696
// these two are not reported because there are two discriminant properties
9797
over = { a: 1, b: 1, first: "ok", second: "error" }
9898
over = { a: 1, b: 1, first: "ok", third: "error" }
99+
100+
// Freshness disappears after spreading a union
101+
declare let t0: { a: any, b: any } | { d: any, e: any }
102+
declare let t1: { a: any, b: any, c: any } | { c: any, d: any, e: any }
103+
let t2 = { ...t1 }
104+
t0 = t2
99105

tests/baselines/reference/excessPropertyCheckWithUnions.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,24 @@ let over: Overlapping
4949
// these two are not reported because there are two discriminant properties
5050
over = { a: 1, b: 1, first: "ok", second: "error" }
5151
over = { a: 1, b: 1, first: "ok", third: "error" }
52+
53+
// Freshness disappears after spreading a union
54+
declare let t0: { a: any, b: any } | { d: any, e: any }
55+
declare let t1: { a: any, b: any, c: any } | { c: any, d: any, e: any }
56+
let t2 = { ...t1 }
57+
t0 = t2
5258

5359

5460
//// [excessPropertyCheckWithUnions.js]
61+
"use strict";
62+
var __assign = (this && this.__assign) || Object.assign || function(t) {
63+
for (var s, i = 1, n = arguments.length; i < n; i++) {
64+
s = arguments[i];
65+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
66+
t[p] = s[p];
67+
}
68+
return t;
69+
};
5570
var wrong = { tag: "T", a1: "extra" };
5671
wrong = { tag: "A", d20: 12 };
5772
wrong = { tag: "D" };
@@ -72,3 +87,5 @@ var over;
7287
// these two are not reported because there are two discriminant properties
7388
over = { a: 1, b: 1, first: "ok", second: "error" };
7489
over = { a: 1, b: 1, first: "ok", third: "error" };
90+
var t2 = __assign({}, t1);
91+
t0 = t2;

tests/baselines/reference/excessPropertyCheckWithUnions.symbols

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,28 @@ over = { a: 1, b: 1, first: "ok", third: "error" }
142142
>first : Symbol(first, Decl(excessPropertyCheckWithUnions.ts, 49, 20))
143143
>third : Symbol(third, Decl(excessPropertyCheckWithUnions.ts, 49, 33))
144144

145+
// Freshness disappears after spreading a union
146+
declare let t0: { a: any, b: any } | { d: any, e: any }
147+
>t0 : Symbol(t0, Decl(excessPropertyCheckWithUnions.ts, 52, 11))
148+
>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 52, 17))
149+
>b : Symbol(b, Decl(excessPropertyCheckWithUnions.ts, 52, 25))
150+
>d : Symbol(d, Decl(excessPropertyCheckWithUnions.ts, 52, 38))
151+
>e : Symbol(e, Decl(excessPropertyCheckWithUnions.ts, 52, 46))
152+
153+
declare let t1: { a: any, b: any, c: any } | { c: any, d: any, e: any }
154+
>t1 : Symbol(t1, Decl(excessPropertyCheckWithUnions.ts, 53, 11))
155+
>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 53, 17))
156+
>b : Symbol(b, Decl(excessPropertyCheckWithUnions.ts, 53, 25))
157+
>c : Symbol(c, Decl(excessPropertyCheckWithUnions.ts, 53, 33))
158+
>c : Symbol(c, Decl(excessPropertyCheckWithUnions.ts, 53, 46))
159+
>d : Symbol(d, Decl(excessPropertyCheckWithUnions.ts, 53, 54))
160+
>e : Symbol(e, Decl(excessPropertyCheckWithUnions.ts, 53, 62))
161+
162+
let t2 = { ...t1 }
163+
>t2 : Symbol(t2, Decl(excessPropertyCheckWithUnions.ts, 54, 3))
164+
>t1 : Symbol(t1, Decl(excessPropertyCheckWithUnions.ts, 53, 11))
165+
166+
t0 = t2
167+
>t0 : Symbol(t0, Decl(excessPropertyCheckWithUnions.ts, 52, 11))
168+
>t2 : Symbol(t2, Decl(excessPropertyCheckWithUnions.ts, 54, 3))
169+

tests/baselines/reference/excessPropertyCheckWithUnions.types

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,30 @@ over = { a: 1, b: 1, first: "ok", third: "error" }
194194
>third : string
195195
>"error" : "error"
196196

197+
// Freshness disappears after spreading a union
198+
declare let t0: { a: any, b: any } | { d: any, e: any }
199+
>t0 : { a: any; b: any; } | { d: any; e: any; }
200+
>a : any
201+
>b : any
202+
>d : any
203+
>e : any
204+
205+
declare let t1: { a: any, b: any, c: any } | { c: any, d: any, e: any }
206+
>t1 : { a: any; b: any; c: any; } | { c: any; d: any; e: any; }
207+
>a : any
208+
>b : any
209+
>c : any
210+
>c : any
211+
>d : any
212+
>e : any
213+
214+
let t2 = { ...t1 }
215+
>t2 : { a: any; b: any; c: any; } | { c: any; d: any; e: any; }
216+
>{ ...t1 } : { a: any; b: any; c: any; } | { c: any; d: any; e: any; }
217+
>t1 : { a: any; b: any; c: any; } | { c: any; d: any; e: any; }
218+
219+
t0 = t2
220+
>t0 = t2 : { a: any; b: any; c: any; } | { c: any; d: any; e: any; }
221+
>t0 : { a: any; b: any; } | { d: any; e: any; }
222+
>t2 : { a: any; b: any; c: any; } | { c: any; d: any; e: any; }
223+

tests/baselines/reference/spreadInvalidArgumentType.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ function f<T extends { b: string }>(p1: T, p2: T[]) {
8989
>p1 : T
9090

9191
var o2 = { ...p2 }; // OK
92-
>o2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray<T>[]): T[]; concat(...items: (T | ReadonlyArray<T>)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; }
92+
>o2 : { [x: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray<T>[]): T[]; concat(...items: (T | ReadonlyArray<T>)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; }
9393
>{ ...p2 } : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray<T>[]): T[]; concat(...items: (T | ReadonlyArray<T>)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; }
9494
>p2 : T[]
9595

tests/cases/compiler/excessPropertyCheckWithUnions.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// @strict: true
12
type ADT = {
23
tag: "A",
34
a1: string
@@ -48,3 +49,9 @@ let over: Overlapping
4849
// these two are not reported because there are two discriminant properties
4950
over = { a: 1, b: 1, first: "ok", second: "error" }
5051
over = { a: 1, b: 1, first: "ok", third: "error" }
52+
53+
// Freshness disappears after spreading a union
54+
declare let t0: { a: any, b: any } | { d: any, e: any }
55+
declare let t1: { a: any, b: any, c: any } | { c: any, d: any, e: any }
56+
let t2 = { ...t1 }
57+
t0 = t2

0 commit comments

Comments
 (0)