Skip to content

Commit 4e9d35b

Browse files
committed
Do not enable object literal freshness checks on jsx spreads
1 parent f515e13 commit 4e9d35b

File tree

3 files changed

+11
-15
lines changed

3 files changed

+11
-15
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7971,8 +7971,7 @@ namespace ts {
79717971
}
79727972

79737973
const spread = createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
7974-
spread.flags |= propagatedFlags;
7975-
spread.flags |= TypeFlags.FreshLiteral;
7974+
spread.flags |= propagatedFlags | TypeFlags.ContainsObjectLiteral;
79767975
(spread as ObjectType).objectFlags |= ObjectFlags.ObjectLiteral;
79777976
spread.symbol = symbol;
79787977
return spread;
@@ -13872,7 +13871,7 @@ namespace ts {
1387213871
let propertiesTable = createSymbolTable();
1387313872
let propertiesArray: Symbol[] = [];
1387413873
let spread: Type = emptyObjectType;
13875-
let propagatedFlags: TypeFlags = 0;
13874+
let propagatedFlags: TypeFlags = TypeFlags.FreshLiteral;
1387613875

1387713876
const contextualType = getApparentTypeOfContextualType(node);
1387813877
const contextualTypeHasPattern = contextualType && contextualType.pattern &&
@@ -14110,7 +14109,7 @@ namespace ts {
1411014109
function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode) {
1411114110
const attributes = openingLikeElement.attributes;
1411214111
let attributesTable = createSymbolTable();
14113-
let spread: Type = neverType;
14112+
let spread: Type = emptyObjectType;
1411414113
let hasSpreadAnyType = false;
1411514114
let typeToIntersect: Type;
1411614115
let explicitlySpecifyChildrenAttribute = false;
@@ -14201,10 +14200,7 @@ namespace ts {
1420114200
if (hasSpreadAnyType) {
1420214201
return anyType;
1420314202
}
14204-
if (spread !== neverType) {
14205-
return typeToIntersect ? getIntersectionType([typeToIntersect, spread]) : spread;
14206-
}
14207-
return typeToIntersect ? typeToIntersect : emptyObjectType;
14203+
return typeToIntersect ? getIntersectionType([typeToIntersect, ...spread === emptyObjectType ? [] : [spread]]) : spread;
1420814204

1420914205
/**
1421014206
* Create anonymous type from given attributes symbol table.

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/baselines/reference/tsxSpreadAttributesResolution16.errors.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
tests/cases/conformance/jsx/file.tsx(11,27): error TS2322: Type 'ComponentProps' is not assignable to type 'IntrinsicAttributes & AnotherComponentProps'.
2-
Type 'ComponentProps' is not assignable to type 'AnotherComponentProps'.
3-
Property 'AnotherProperty1' is missing in type 'ComponentProps'.
1+
tests/cases/conformance/jsx/file.tsx(11,27): error TS2322: Type '{ property1: string; property2: number; }' is not assignable to type 'IntrinsicAttributes & AnotherComponentProps'.
2+
Type '{ property1: string; property2: number; }' is not assignable to type 'AnotherComponentProps'.
3+
Property 'AnotherProperty1' is missing in type '{ property1: string; property2: number; }'.
44

55

66
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
@@ -16,9 +16,9 @@ tests/cases/conformance/jsx/file.tsx(11,27): error TS2322: Type 'ComponentProps'
1616
// Error: missing property
1717
<AnotherComponent {...props} />
1818
~~~~~~~~~~
19-
!!! error TS2322: Type 'ComponentProps' is not assignable to type 'IntrinsicAttributes & AnotherComponentProps'.
20-
!!! error TS2322: Type 'ComponentProps' is not assignable to type 'AnotherComponentProps'.
21-
!!! error TS2322: Property 'AnotherProperty1' is missing in type 'ComponentProps'.
19+
!!! error TS2322: Type '{ property1: string; property2: number; }' is not assignable to type 'IntrinsicAttributes & AnotherComponentProps'.
20+
!!! error TS2322: Type '{ property1: string; property2: number; }' is not assignable to type 'AnotherComponentProps'.
21+
!!! error TS2322: Property 'AnotherProperty1' is missing in type '{ property1: string; property2: number; }'.
2222
);
2323
}
2424

0 commit comments

Comments
 (0)