Merge pull request #18363 from Microsoft/fixIntersectionInference
Fix intersection inference
This commit is contained in:
commit
d65a3e1c67
7 changed files with 162 additions and 6 deletions
|
@ -10579,7 +10579,7 @@ namespace ts {
|
|||
priority = savePriority;
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.UnionOrIntersection) {
|
||||
else if (source.flags & TypeFlags.Union) {
|
||||
// Source is a union or intersection type, infer from each constituent type
|
||||
const sourceTypes = (<UnionOrIntersectionType>source).types;
|
||||
for (const sourceType of sourceTypes) {
|
||||
|
@ -10588,7 +10588,7 @@ namespace ts {
|
|||
}
|
||||
else {
|
||||
source = getApparentType(source);
|
||||
if (source.flags & TypeFlags.Object) {
|
||||
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection)) {
|
||||
const key = source.id + "," + target.id;
|
||||
if (visited && visited.get(key)) {
|
||||
return;
|
||||
|
@ -10668,7 +10668,7 @@ namespace ts {
|
|||
function inferFromProperties(source: Type, target: Type) {
|
||||
const properties = getPropertiesOfObjectType(target);
|
||||
for (const targetProp of properties) {
|
||||
const sourceProp = getPropertyOfObjectType(source, targetProp.escapedName);
|
||||
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
|
||||
if (sourceProp) {
|
||||
inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
|
||||
}
|
||||
|
|
23
tests/baselines/reference/intersectionTypeInference2.js
Normal file
23
tests/baselines/reference/intersectionTypeInference2.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
//// [intersectionTypeInference2.ts]
|
||||
declare function f<T>(x: { prop: T }): T;
|
||||
|
||||
declare const a: { prop: string } & { prop: number };
|
||||
declare const b: { prop: string & number };
|
||||
|
||||
f(a); // string & number
|
||||
f(b); // string & number
|
||||
|
||||
// Repro from #18354
|
||||
|
||||
declare function f2<T, Key extends keyof T>(obj: {[K in keyof T]: T[K]}, key: Key): T[Key];
|
||||
|
||||
declare const obj: { a: string } & { b: string };
|
||||
f2(obj, 'a');
|
||||
f2(obj, 'b');
|
||||
|
||||
|
||||
//// [intersectionTypeInference2.js]
|
||||
f(a); // string & number
|
||||
f(b); // string & number
|
||||
f2(obj, 'a');
|
||||
f2(obj, 'b');
|
56
tests/baselines/reference/intersectionTypeInference2.symbols
Normal file
56
tests/baselines/reference/intersectionTypeInference2.symbols
Normal file
|
@ -0,0 +1,56 @@
|
|||
=== tests/cases/conformance/types/intersection/intersectionTypeInference2.ts ===
|
||||
declare function f<T>(x: { prop: T }): T;
|
||||
>f : Symbol(f, Decl(intersectionTypeInference2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(intersectionTypeInference2.ts, 0, 19))
|
||||
>x : Symbol(x, Decl(intersectionTypeInference2.ts, 0, 22))
|
||||
>prop : Symbol(prop, Decl(intersectionTypeInference2.ts, 0, 26))
|
||||
>T : Symbol(T, Decl(intersectionTypeInference2.ts, 0, 19))
|
||||
>T : Symbol(T, Decl(intersectionTypeInference2.ts, 0, 19))
|
||||
|
||||
declare const a: { prop: string } & { prop: number };
|
||||
>a : Symbol(a, Decl(intersectionTypeInference2.ts, 2, 13))
|
||||
>prop : Symbol(prop, Decl(intersectionTypeInference2.ts, 2, 18))
|
||||
>prop : Symbol(prop, Decl(intersectionTypeInference2.ts, 2, 37))
|
||||
|
||||
declare const b: { prop: string & number };
|
||||
>b : Symbol(b, Decl(intersectionTypeInference2.ts, 3, 13))
|
||||
>prop : Symbol(prop, Decl(intersectionTypeInference2.ts, 3, 18))
|
||||
|
||||
f(a); // string & number
|
||||
>f : Symbol(f, Decl(intersectionTypeInference2.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(intersectionTypeInference2.ts, 2, 13))
|
||||
|
||||
f(b); // string & number
|
||||
>f : Symbol(f, Decl(intersectionTypeInference2.ts, 0, 0))
|
||||
>b : Symbol(b, Decl(intersectionTypeInference2.ts, 3, 13))
|
||||
|
||||
// Repro from #18354
|
||||
|
||||
declare function f2<T, Key extends keyof T>(obj: {[K in keyof T]: T[K]}, key: Key): T[Key];
|
||||
>f2 : Symbol(f2, Decl(intersectionTypeInference2.ts, 6, 5))
|
||||
>T : Symbol(T, Decl(intersectionTypeInference2.ts, 10, 20))
|
||||
>Key : Symbol(Key, Decl(intersectionTypeInference2.ts, 10, 22))
|
||||
>T : Symbol(T, Decl(intersectionTypeInference2.ts, 10, 20))
|
||||
>obj : Symbol(obj, Decl(intersectionTypeInference2.ts, 10, 44))
|
||||
>K : Symbol(K, Decl(intersectionTypeInference2.ts, 10, 51))
|
||||
>T : Symbol(T, Decl(intersectionTypeInference2.ts, 10, 20))
|
||||
>T : Symbol(T, Decl(intersectionTypeInference2.ts, 10, 20))
|
||||
>K : Symbol(K, Decl(intersectionTypeInference2.ts, 10, 51))
|
||||
>key : Symbol(key, Decl(intersectionTypeInference2.ts, 10, 72))
|
||||
>Key : Symbol(Key, Decl(intersectionTypeInference2.ts, 10, 22))
|
||||
>T : Symbol(T, Decl(intersectionTypeInference2.ts, 10, 20))
|
||||
>Key : Symbol(Key, Decl(intersectionTypeInference2.ts, 10, 22))
|
||||
|
||||
declare const obj: { a: string } & { b: string };
|
||||
>obj : Symbol(obj, Decl(intersectionTypeInference2.ts, 12, 13))
|
||||
>a : Symbol(a, Decl(intersectionTypeInference2.ts, 12, 20))
|
||||
>b : Symbol(b, Decl(intersectionTypeInference2.ts, 12, 36))
|
||||
|
||||
f2(obj, 'a');
|
||||
>f2 : Symbol(f2, Decl(intersectionTypeInference2.ts, 6, 5))
|
||||
>obj : Symbol(obj, Decl(intersectionTypeInference2.ts, 12, 13))
|
||||
|
||||
f2(obj, 'b');
|
||||
>f2 : Symbol(f2, Decl(intersectionTypeInference2.ts, 6, 5))
|
||||
>obj : Symbol(obj, Decl(intersectionTypeInference2.ts, 12, 13))
|
||||
|
62
tests/baselines/reference/intersectionTypeInference2.types
Normal file
62
tests/baselines/reference/intersectionTypeInference2.types
Normal file
|
@ -0,0 +1,62 @@
|
|||
=== tests/cases/conformance/types/intersection/intersectionTypeInference2.ts ===
|
||||
declare function f<T>(x: { prop: T }): T;
|
||||
>f : <T>(x: { prop: T; }) => T
|
||||
>T : T
|
||||
>x : { prop: T; }
|
||||
>prop : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
declare const a: { prop: string } & { prop: number };
|
||||
>a : { prop: string; } & { prop: number; }
|
||||
>prop : string
|
||||
>prop : number
|
||||
|
||||
declare const b: { prop: string & number };
|
||||
>b : { prop: string & number; }
|
||||
>prop : string & number
|
||||
|
||||
f(a); // string & number
|
||||
>f(a) : string & number
|
||||
>f : <T>(x: { prop: T; }) => T
|
||||
>a : { prop: string; } & { prop: number; }
|
||||
|
||||
f(b); // string & number
|
||||
>f(b) : string & number
|
||||
>f : <T>(x: { prop: T; }) => T
|
||||
>b : { prop: string & number; }
|
||||
|
||||
// Repro from #18354
|
||||
|
||||
declare function f2<T, Key extends keyof T>(obj: {[K in keyof T]: T[K]}, key: Key): T[Key];
|
||||
>f2 : <T, Key extends keyof T>(obj: { [K in keyof T]: T[K]; }, key: Key) => T[Key]
|
||||
>T : T
|
||||
>Key : Key
|
||||
>T : T
|
||||
>obj : { [K in keyof T]: T[K]; }
|
||||
>K : K
|
||||
>T : T
|
||||
>T : T
|
||||
>K : K
|
||||
>key : Key
|
||||
>Key : Key
|
||||
>T : T
|
||||
>Key : Key
|
||||
|
||||
declare const obj: { a: string } & { b: string };
|
||||
>obj : { a: string; } & { b: string; }
|
||||
>a : string
|
||||
>b : string
|
||||
|
||||
f2(obj, 'a');
|
||||
>f2(obj, 'a') : string
|
||||
>f2 : <T, Key extends keyof T>(obj: { [K in keyof T]: T[K]; }, key: Key) => T[Key]
|
||||
>obj : { a: string; } & { b: string; }
|
||||
>'a' : "a"
|
||||
|
||||
f2(obj, 'b');
|
||||
>f2(obj, 'b') : string
|
||||
>f2 : <T, Key extends keyof T>(obj: { [K in keyof T]: T[K]; }, key: Key) => T[Key]
|
||||
>obj : { a: string; } & { b: string; }
|
||||
>'b' : "b"
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
declare function f<T>(x: { prop: T }): T;
|
||||
|
||||
declare const a: { prop: string } & { prop: number };
|
||||
declare const b: { prop: string & number };
|
||||
|
||||
f(a); // string & number
|
||||
f(b); // string & number
|
||||
|
||||
// Repro from #18354
|
||||
|
||||
declare function f2<T, Key extends keyof T>(obj: {[K in keyof T]: T[K]}, key: Key): T[Key];
|
||||
|
||||
declare const obj: { a: string } & { b: string };
|
||||
f2(obj, 'a');
|
||||
f2(obj, 'b');
|
|
@ -15,5 +15,5 @@
|
|||
|
||||
verify.quickInfos({
|
||||
1: "function ComponentSpecific<number>(l: {\n prop: number;\n}): any",
|
||||
2: "function ComponentSpecific<number>(l: {\n prop: number;\n}): any"
|
||||
2: "function ComponentSpecific<number & \"hello\">(l: {\n prop: number & \"hello\";\n}): any"
|
||||
});
|
||||
|
|
|
@ -24,6 +24,6 @@ verify.quickInfos({
|
|||
3: "function OverloadComponent<boolean, string>(attr: {\n b: string;\n a: boolean;\n}): any (+2 overloads)",
|
||||
4: "function OverloadComponent<number>(attr: {\n b: number;\n a?: string;\n \"ignore-prop\": boolean;\n}): any (+2 overloads)",
|
||||
5: "function OverloadComponent(): any (+2 overloads)",
|
||||
6: "function OverloadComponent<boolean, string>(attr: {\n b: string;\n a: boolean;\n}): any (+2 overloads)",
|
||||
7: "function OverloadComponent<boolean, number>(attr: {\n b: number;\n a: boolean;\n}): any (+2 overloads)",
|
||||
6: "function OverloadComponent<boolean, string & number>(attr: {\n b: string & number;\n a: boolean;\n}): any (+2 overloads)",
|
||||
7: "function OverloadComponent<boolean, number & string>(attr: {\n b: number & string;\n a: boolean;\n}): any (+2 overloads)",
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue