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
This commit is contained in:
Wesley Wigham 2018-10-17 14:44:39 -07:00 committed by GitHub
parent 7b5ef64e76
commit 9554f09d09
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 189 additions and 0 deletions

View file

@ -13644,6 +13644,17 @@ namespace ts {
}
return;
}
else {
// Infer to the simplified version of an indexed access, if possible, to (hopefully) expose more bare type parameters to the inference engine
const simplified = getSimplifiedType(target);
if (simplified !== target) {
const key = source.id + "," + simplified.id;
if (!visited || !visited.get(key)) {
(visited || (visited = createMap<boolean>())).set(key, true);
inferFromTypes(source, simplified);
}
}
}
}
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
// If source and target are references to the same generic type, infer from type arguments

View file

@ -0,0 +1,33 @@
//// [complicatedIndexesOfIntersectionsAreInferencable.ts]
interface FormikConfig<Values> {
initialValues: Values;
validate?: (props: Values) => void;
validateOnChange?: boolean;
}
declare function 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;
Func({
initialValues: {
foo: ""
},
validate: props => {
props.foo;
}
});
//// [complicatedIndexesOfIntersectionsAreInferencable.js]
"use strict";
Func({
initialValues: {
foo: ""
},
validate: function (props) {
props.foo;
}
});

View file

@ -0,0 +1,74 @@
=== tests/cases/compiler/complicatedIndexesOfIntersectionsAreInferencable.ts ===
interface FormikConfig<Values> {
>FormikConfig : Symbol(FormikConfig, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 0))
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 23))
initialValues: Values;
>initialValues : Symbol(FormikConfig.initialValues, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 32))
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 23))
validate?: (props: Values) => void;
>validate : Symbol(FormikConfig.validate, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 1, 26))
>props : Symbol(props, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 2, 16))
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 23))
validateOnChange?: boolean;
>validateOnChange : Symbol(FormikConfig.validateOnChange, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 2, 39))
}
declare function Func<Values = object, ExtraProps = {}>(
>Func : Symbol(Func, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 4, 1))
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 22))
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
x: (string extends "validate" | "initialValues" | keyof ExtraProps
>x : Symbol(x, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 56))
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
? Readonly<FormikConfig<Values> & ExtraProps>
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
>FormikConfig : Symbol(FormikConfig, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 0))
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 22))
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
: Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validate" | "initialValues" | Exclude<keyof ExtraProps, "validateOnChange">>
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
>FormikConfig : Symbol(FormikConfig, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 0))
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 22))
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
& Partial<Pick<Readonly<FormikConfig<Values> & ExtraProps>, "validateOnChange" | Extract<keyof ExtraProps, "validateOnChange">>>)
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
>FormikConfig : Symbol(FormikConfig, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 0, 0))
>Values : Symbol(Values, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 22))
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>ExtraProps : Symbol(ExtraProps, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 6, 38))
): void;
Func({
>Func : Symbol(Func, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 4, 1))
initialValues: {
>initialValues : Symbol(initialValues, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 13, 6))
foo: ""
>foo : Symbol(foo, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 14, 20))
},
validate: props => {
>validate : Symbol(validate, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 16, 6))
>props : Symbol(props, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 17, 13))
props.foo;
>props.foo : Symbol(foo, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 14, 20))
>props : Symbol(props, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 17, 13))
>foo : Symbol(foo, Decl(complicatedIndexesOfIntersectionsAreInferencable.ts, 14, 20))
}
});

View file

@ -0,0 +1,49 @@
=== tests/cases/compiler/complicatedIndexesOfIntersectionsAreInferencable.ts ===
interface FormikConfig<Values> {
initialValues: Values;
>initialValues : Values
validate?: (props: Values) => void;
>validate : ((props: Values) => void) | undefined
>props : Values
validateOnChange?: boolean;
>validateOnChange : boolean | undefined
}
declare function Func<Values = object, ExtraProps = {}>(
>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
x: (string extends "validate" | "initialValues" | keyof 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">>>
? 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;
Func({
>Func({ initialValues: { foo: "" }, validate: props => { props.foo; }}) : void
>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
>{ initialValues: { foo: "" }, validate: props => { props.foo; }} : { initialValues: { foo: string; }; validate: (props: { foo: string; }) => void; }
initialValues: {
>initialValues : { foo: string; }
>{ foo: "" } : { foo: string; }
foo: ""
>foo : string
>"" : ""
},
validate: props => {
>validate : (props: { foo: string; }) => void
>props => { props.foo; } : (props: { foo: string; }) => void
>props : { foo: string; }
props.foo;
>props.foo : string
>props : { foo: string; }
>foo : string
}
});

View file

@ -0,0 +1,22 @@
// @strict: true
interface FormikConfig<Values> {
initialValues: Values;
validate?: (props: Values) => void;
validateOnChange?: boolean;
}
declare function 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;
Func({
initialValues: {
foo: ""
},
validate: props => {
props.foo;
}
});