Skip to content

Commit 9554f09

Browse files
authored
Add ability to infer to the simplified form of a type variable (#27953)
* Add ability to infer to the simplified form of a type variable * Add test
1 parent 7b5ef64 commit 9554f09

5 files changed

+189
-0
lines changed

src/compiler/checker.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13644,6 +13644,17 @@ namespace ts {
1364413644
}
1364513645
return;
1364613646
}
13647+
else {
13648+
// Infer to the simplified version of an indexed access, if possible, to (hopefully) expose more bare type parameters to the inference engine
13649+
const simplified = getSimplifiedType(target);
13650+
if (simplified !== target) {
13651+
const key = source.id + "," + simplified.id;
13652+
if (!visited || !visited.get(key)) {
13653+
(visited || (visited = createMap<boolean>())).set(key, true);
13654+
inferFromTypes(source, simplified);
13655+
}
13656+
}
13657+
}
1364713658
}
1364813659
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
1364913660
// If source and target are references to the same generic type, infer from type arguments
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//// [complicatedIndexesOfIntersectionsAreInferencable.ts]
2+
interface FormikConfig<Values> {
3+
initialValues: Values;
4+
validate?: (props: Values) => void;
5+
validateOnChange?: boolean;
6+
}
7+
8+
declare function Func<Values = object, ExtraProps = {}>(
9+
x: (string extends "validate" | "initialValues" | keyof ExtraProps
10+
? Readonly<FormikConfig<Values> & ExtraProps>
11+
: Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">>
12+
& Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>)
13+
): void;
14+
15+
Func({
16+
initialValues: {
17+
foo: ""
18+
},
19+
validate: props => {
20+
props.foo;
21+
}
22+
});
23+
24+
//// [complicatedIndexesOfIntersectionsAreInferencable.js]
25+
"use strict";
26+
Func({
27+
initialValues: {
28+
foo: ""
29+
},
30+
validate: function (props) {
31+
props.foo;
32+
}
33+
});
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
=== tests/cases/compiler/complicatedIndexesOfIntersectionsAreInferencable.ts ===
2+
interface FormikConfig<Values> {
3+
>FormikConfig : Symbol(FormikConfig, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 0))
4+
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 23))
5+
6+
initialValues: Values;
7+
>initialValues : Symbol(FormikConfig.initialValues, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 32))
8+
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 23))
9+
10+
validate?: (props: Values) => void;
11+
>validate : Symbol(FormikConfig.validate, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 1, 26))
12+
>props : Symbol(props, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 2, 16))
13+
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 23))
14+
15+
validateOnChange?: boolean;
16+
>validateOnChange : Symbol(FormikConfig.validateOnChange, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 2, 39))
17+
}
18+
19+
declare function Func<Values = object, ExtraProps = {}>(
20+
>Func : Symbol(Func, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 4, 1))
21+
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 22))
22+
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
23+
24+
x: (string extends "validate" | "initialValues" | keyof ExtraProps
25+
>x : Symbol(x, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 56))
26+
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
27+
28+
? Readonly<FormikConfig<Values> & ExtraProps>
29+
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
30+
>FormikConfig : Symbol(FormikConfig, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 0))
31+
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 22))
32+
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
33+
34+
: Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">>
35+
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
36+
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
37+
>FormikConfig : Symbol(FormikConfig, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 0))
38+
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 22))
39+
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
40+
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
41+
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
42+
43+
& Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>)
44+
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
45+
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
46+
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
47+
>FormikConfig : Symbol(FormikConfig, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 0))
48+
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 22))
49+
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
50+
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
51+
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
52+
53+
): void;
54+
55+
Func({
56+
>Func : Symbol(Func, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 4, 1))
57+
58+
initialValues: {
59+
>initialValues : Symbol(initialValues, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 13, 6))
60+
61+
foo: ""
62+
>foo : Symbol(foo, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 14, 20))
63+
64+
},
65+
validate: props => {
66+
>validate : Symbol(validate, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 16, 6))
67+
>props : Symbol(props, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 17, 13))
68+
69+
props.foo;
70+
>props.foo : Symbol(foo, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 14, 20))
71+
>props : Symbol(props, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 17, 13))
72+
>foo : Symbol(foo, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 14, 20))
73+
}
74+
});
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
=== tests/cases/compiler/complicatedIndexesOfIntersectionsAreInferencable.ts ===
2+
interface FormikConfig<Values> {
3+
initialValues: Values;
4+
>initialValues : Values
5+
6+
validate?: (props: Values) => void;
7+
>validate : ((props: Values) => void) | undefined
8+
>props : Values
9+
10+
validateOnChange?: boolean;
11+
>validateOnChange : boolean | undefined
12+
}
13+
14+
declare function Func<Values = object, ExtraProps = {}>(
15+
>Func : <Values = object, ExtraProps = {}>(x: string extends "validate" | "initialValues" | keyof ExtraProps ? Readonly<FormikConfig<Values> & ExtraProps> : Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">> & Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>) => void
16+
17+
x: (string extends "validate" | "initialValues" | keyof ExtraProps
18+
>x : string extends "validate" | "initialValues" | keyof ExtraProps ? Readonly<FormikConfig<Values> & ExtraProps> : Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">> & Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>
19+
20+
? Readonly<FormikConfig<Values> & ExtraProps>
21+
: Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">>
22+
& Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>)
23+
): void;
24+
25+
Func({
26+
>Func({ initialValues: { foo: "" }, validate: props => { props.foo; }}) : void
27+
>Func : <Values = object, ExtraProps = {}>(x: string extends "validate" | "initialValues" | keyof ExtraProps ? Readonly<FormikConfig<Values> & ExtraProps> : Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">> & Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>) => void
28+
>{ initialValues: { foo: "" }, validate: props => { props.foo; }} : { initialValues: { foo: string; }; validate: (props: { foo: string; }) => void; }
29+
30+
initialValues: {
31+
>initialValues : { foo: string; }
32+
>{ foo: "" } : { foo: string; }
33+
34+
foo: ""
35+
>foo : string
36+
>"" : ""
37+
38+
},
39+
validate: props => {
40+
>validate : (props: { foo: string; }) => void
41+
>props => { props.foo; } : (props: { foo: string; }) => void
42+
>props : { foo: string; }
43+
44+
props.foo;
45+
>props.foo : string
46+
>props : { foo: string; }
47+
>foo : string
48+
}
49+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// @strict: true
2+
interface FormikConfig<Values> {
3+
initialValues: Values;
4+
validate?: (props: Values) => void;
5+
validateOnChange?: boolean;
6+
}
7+
8+
declare function Func<Values = object, ExtraProps = {}>(
9+
x: (string extends "validate" | "initialValues" | keyof ExtraProps
10+
? Readonly<FormikConfig<Values> & ExtraProps>
11+
: Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">>
12+
& Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>)
13+
): void;
14+
15+
Func({
16+
initialValues: {
17+
foo: ""
18+
},
19+
validate: props => {
20+
props.foo;
21+
}
22+
});

0 commit comments

Comments
 (0)