Skip to content

Commit 1321d2a

Browse files
authored
Merge pull request #19701 from Microsoft/fixIntersectionTypeInference
Fix intersection type inference
2 parents a8d3cd6 + 9bb6a52 commit 1321d2a

File tree

6 files changed

+170
-7
lines changed

6 files changed

+170
-7
lines changed

src/compiler/checker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10807,7 +10807,7 @@ namespace ts {
1080710807
}
1080810808

1080910809
function getUnmatchedProperty(source: Type, target: Type, requireOptionalProperties: boolean) {
10810-
const properties = getPropertiesOfObjectType(target);
10810+
const properties = target.flags & TypeFlags.Intersection ? getPropertiesOfUnionOrIntersectionType(<IntersectionType>target) : getPropertiesOfObjectType(target);
1081110811
for (const targetProp of properties) {
1081210812
if (requireOptionalProperties || !(targetProp.flags & SymbolFlags.Optional)) {
1081310813
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [intersectionTypeInference3.ts]
2+
// Repro from #19682
3+
4+
type Nominal<Kind extends string, Type> = Type & {
5+
[Symbol.species]: Kind;
6+
};
7+
8+
type A = Nominal<'A', string>;
9+
10+
declare const a: Set<A>;
11+
declare const b: Set<A>;
12+
13+
const c1 = Array.from(a).concat(Array.from(b));
14+
15+
// Simpler repro
16+
17+
declare function from<T>(): T[];
18+
const c2: ReadonlyArray<A> = from();
19+
20+
21+
//// [intersectionTypeInference3.js]
22+
"use strict";
23+
// Repro from #19682
24+
const c1 = Array.from(a).concat(Array.from(b));
25+
const c2 = from();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
=== tests/cases/conformance/types/intersection/intersectionTypeInference3.ts ===
2+
// Repro from #19682
3+
4+
type Nominal<Kind extends string, Type> = Type & {
5+
>Nominal : Symbol(Nominal, Decl(intersectionTypeInference3.ts, 0, 0))
6+
>Kind : Symbol(Kind, Decl(intersectionTypeInference3.ts, 2, 13))
7+
>Type : Symbol(Type, Decl(intersectionTypeInference3.ts, 2, 33))
8+
>Type : Symbol(Type, Decl(intersectionTypeInference3.ts, 2, 33))
9+
10+
[Symbol.species]: Kind;
11+
>Symbol.species : Symbol(SymbolConstructor.species, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
12+
>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --))
13+
>species : Symbol(SymbolConstructor.species, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
14+
>Kind : Symbol(Kind, Decl(intersectionTypeInference3.ts, 2, 13))
15+
16+
};
17+
18+
type A = Nominal<'A', string>;
19+
>A : Symbol(A, Decl(intersectionTypeInference3.ts, 4, 2))
20+
>Nominal : Symbol(Nominal, Decl(intersectionTypeInference3.ts, 0, 0))
21+
22+
declare const a: Set<A>;
23+
>a : Symbol(a, Decl(intersectionTypeInference3.ts, 8, 13))
24+
>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --))
25+
>A : Symbol(A, Decl(intersectionTypeInference3.ts, 4, 2))
26+
27+
declare const b: Set<A>;
28+
>b : Symbol(b, Decl(intersectionTypeInference3.ts, 9, 13))
29+
>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --))
30+
>A : Symbol(A, Decl(intersectionTypeInference3.ts, 4, 2))
31+
32+
const c1 = Array.from(a).concat(Array.from(b));
33+
>c1 : Symbol(c1, Decl(intersectionTypeInference3.ts, 11, 5))
34+
>Array.from(a).concat : Symbol(Array.concat, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
35+
>Array.from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
36+
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
37+
>from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
38+
>a : Symbol(a, Decl(intersectionTypeInference3.ts, 8, 13))
39+
>concat : Symbol(Array.concat, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
40+
>Array.from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
41+
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
42+
>from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
43+
>b : Symbol(b, Decl(intersectionTypeInference3.ts, 9, 13))
44+
45+
// Simpler repro
46+
47+
declare function from<T>(): T[];
48+
>from : Symbol(from, Decl(intersectionTypeInference3.ts, 11, 47))
49+
>T : Symbol(T, Decl(intersectionTypeInference3.ts, 15, 22))
50+
>T : Symbol(T, Decl(intersectionTypeInference3.ts, 15, 22))
51+
52+
const c2: ReadonlyArray<A> = from();
53+
>c2 : Symbol(c2, Decl(intersectionTypeInference3.ts, 16, 5))
54+
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
55+
>A : Symbol(A, Decl(intersectionTypeInference3.ts, 4, 2))
56+
>from : Symbol(from, Decl(intersectionTypeInference3.ts, 11, 47))
57+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
=== tests/cases/conformance/types/intersection/intersectionTypeInference3.ts ===
2+
// Repro from #19682
3+
4+
type Nominal<Kind extends string, Type> = Type & {
5+
>Nominal : Nominal<Kind, Type>
6+
>Kind : Kind
7+
>Type : Type
8+
>Type : Type
9+
10+
[Symbol.species]: Kind;
11+
>Symbol.species : symbol
12+
>Symbol : SymbolConstructor
13+
>species : symbol
14+
>Kind : Kind
15+
16+
};
17+
18+
type A = Nominal<'A', string>;
19+
>A : Nominal<"A", string>
20+
>Nominal : Nominal<Kind, Type>
21+
22+
declare const a: Set<A>;
23+
>a : Set<Nominal<"A", string>>
24+
>Set : Set<T>
25+
>A : Nominal<"A", string>
26+
27+
declare const b: Set<A>;
28+
>b : Set<Nominal<"A", string>>
29+
>Set : Set<T>
30+
>A : Nominal<"A", string>
31+
32+
const c1 = Array.from(a).concat(Array.from(b));
33+
>c1 : Nominal<"A", string>[]
34+
>Array.from(a).concat(Array.from(b)) : Nominal<"A", string>[]
35+
>Array.from(a).concat : { (...items: ReadonlyArray<Nominal<"A", string>>[]): Nominal<"A", string>[]; (...items: (Nominal<"A", string> | ReadonlyArray<Nominal<"A", string>>)[]): Nominal<"A", string>[]; }
36+
>Array.from(a) : Nominal<"A", string>[]
37+
>Array.from : { <T>(iterable: Iterable<T>): T[]; <T, U>(iterable: Iterable<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; <T>(arrayLike: ArrayLike<T>): T[]; <T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; }
38+
>Array : ArrayConstructor
39+
>from : { <T>(iterable: Iterable<T>): T[]; <T, U>(iterable: Iterable<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; <T>(arrayLike: ArrayLike<T>): T[]; <T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; }
40+
>a : Set<Nominal<"A", string>>
41+
>concat : { (...items: ReadonlyArray<Nominal<"A", string>>[]): Nominal<"A", string>[]; (...items: (Nominal<"A", string> | ReadonlyArray<Nominal<"A", string>>)[]): Nominal<"A", string>[]; }
42+
>Array.from(b) : Nominal<"A", string>[]
43+
>Array.from : { <T>(iterable: Iterable<T>): T[]; <T, U>(iterable: Iterable<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; <T>(arrayLike: ArrayLike<T>): T[]; <T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; }
44+
>Array : ArrayConstructor
45+
>from : { <T>(iterable: Iterable<T>): T[]; <T, U>(iterable: Iterable<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; <T>(arrayLike: ArrayLike<T>): T[]; <T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; }
46+
>b : Set<Nominal<"A", string>>
47+
48+
// Simpler repro
49+
50+
declare function from<T>(): T[];
51+
>from : <T>() => T[]
52+
>T : T
53+
>T : T
54+
55+
const c2: ReadonlyArray<A> = from();
56+
>c2 : ReadonlyArray<Nominal<"A", string>>
57+
>ReadonlyArray : ReadonlyArray<T>
58+
>A : Nominal<"A", string>
59+
>from() : Nominal<"A", string>[]
60+
>from : <T>() => T[]
61+

tests/baselines/reference/tsxStatelessFunctionComponentsWithTypeArguments4.errors.txt

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
tests/cases/conformance/jsx/file.tsx(9,33): error TS2322: Type '{ a: number; }' is not assignable to type 'IntrinsicAttributes & { b: {}; a: number; }'.
22
Type '{ a: number; }' is not assignable to type '{ b: {}; a: number; }'.
33
Property 'b' is missing in type '{ a: number; }'.
4-
tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'.
5-
Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'.
6-
Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'.
4+
tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: {}; a: {}; }'.
5+
Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: {}; a: {}; }'.
6+
Type '{ b: number; }' is not assignable to type '{ b: {}; a: {}; }'.
77
Property 'a' is missing in type '{ b: number; }'.
88
Type 'T' is not assignable to type 'IntrinsicAttributes'.
99
Type '{ b: number; }' has no properties in common with type 'IntrinsicAttributes'.
@@ -25,9 +25,9 @@ tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type 'T' is not assig
2525
!!! error TS2322: Property 'b' is missing in type '{ a: number; }'.
2626
let a2 = <OverloadComponent {...arg1} ignore-prop /> // missing a
2727
~~~~~~~~~~~~~~~~~~~~~
28-
!!! error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'.
29-
!!! error TS2322: Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: number; a: {}; }'.
30-
!!! error TS2322: Type '{ b: number; }' is not assignable to type '{ b: number; a: {}; }'.
28+
!!! error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes & { b: {}; a: {}; }'.
29+
!!! error TS2322: Type '{ b: number; }' is not assignable to type 'IntrinsicAttributes & { b: {}; a: {}; }'.
30+
!!! error TS2322: Type '{ b: number; }' is not assignable to type '{ b: {}; a: {}; }'.
3131
!!! error TS2322: Property 'a' is missing in type '{ b: number; }'.
3232
!!! error TS2322: Type 'T' is not assignable to type 'IntrinsicAttributes'.
3333
!!! error TS2322: Type '{ b: number; }' has no properties in common with type 'IntrinsicAttributes'.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// @strict: true
2+
// @target: es2015
3+
4+
// Repro from #19682
5+
6+
type Nominal<Kind extends string, Type> = Type & {
7+
[Symbol.species]: Kind;
8+
};
9+
10+
type A = Nominal<'A', string>;
11+
12+
declare const a: Set<A>;
13+
declare const b: Set<A>;
14+
15+
const c1 = Array.from(a).concat(Array.from(b));
16+
17+
// Simpler repro
18+
19+
declare function from<T>(): T[];
20+
const c2: ReadonlyArray<A> = from();

0 commit comments

Comments
 (0)