Allow drawing inferences to conditional type branches (#27012)

* Allow drawing inferences to conditional type branches

* Fix lint
This commit is contained in:
Wesley Wigham 2018-09-17 15:19:23 -07:00 committed by GitHub
parent c3b4f72498
commit a55c0b7df9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 287 additions and 1 deletions

View file

@ -13508,6 +13508,9 @@ namespace ts {
inferFromTypes(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target));
inferFromTypes(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target));
}
else if (target.flags & TypeFlags.Conditional) {
inferFromTypes(source, getUnionType([getTrueTypeFromConditionalType(<ConditionalType>target), getFalseTypeFromConditionalType(<ConditionalType>target)]));
}
else if (target.flags & TypeFlags.UnionOrIntersection) {
const targetTypes = (<UnionOrIntersectionType>target).types;
let typeVariableCount = 0;
@ -13754,7 +13757,7 @@ namespace ts {
function hasPrimitiveConstraint(type: TypeParameter): boolean {
const constraint = getConstraintOfTypeParameter(type);
return !!constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index);
return !!constraint && maybeTypeOfKind(constraint.flags & TypeFlags.Conditional ? getDefaultConstraintOfConditionalType(constraint as ConditionalType) : constraint, TypeFlags.Primitive | TypeFlags.Index);
}
function isObjectLiteralType(type: Type) {

View file

@ -0,0 +1,38 @@
tests/cases/compiler/extractInferenceImprovement.ts(26,26): error TS2345: Argument of type 'unique symbol' is not assignable to parameter of type 'never'.
tests/cases/compiler/extractInferenceImprovement.ts(28,26): error TS2345: Argument of type 'unique symbol' is not assignable to parameter of type '"first" | "second"'.
==== tests/cases/compiler/extractInferenceImprovement.ts (2 errors) ====
// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065
function getProperty2<T, K extends keyof T>(obj: T, key: Extract<K, string>): T[K] {
return obj[key];
}
function getProperty3<T, K extends Extract<keyof T, string>>(obj: T, key: K): T[K] {
return obj[key];
}
const s = Symbol();
interface StrNum {
first: string;
second: number;
[s]: string;
}
const obj: StrNum = {} as any;
let prop: string;
// should work
prop = getProperty2(obj, 'first');
prop = getProperty3(obj, 'first');
// Should fail
prop = getProperty2(obj, s);
~
!!! error TS2345: Argument of type 'unique symbol' is not assignable to parameter of type 'never'.
prop = getProperty3(obj, s);
~
!!! error TS2345: Argument of type 'unique symbol' is not assignable to parameter of type '"first" | "second"'.

View file

@ -0,0 +1,48 @@
//// [extractInferenceImprovement.ts]
// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065
function getProperty2<T, K extends keyof T>(obj: T, key: Extract<K, string>): T[K] {
return obj[key];
}
function getProperty3<T, K extends Extract<keyof T, string>>(obj: T, key: K): T[K] {
return obj[key];
}
const s = Symbol();
interface StrNum {
first: string;
second: number;
[s]: string;
}
const obj: StrNum = {} as any;
let prop: string;
// should work
prop = getProperty2(obj, 'first');
prop = getProperty3(obj, 'first');
// Should fail
prop = getProperty2(obj, s);
prop = getProperty3(obj, s);
//// [extractInferenceImprovement.js]
// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065
function getProperty2(obj, key) {
return obj[key];
}
function getProperty3(obj, key) {
return obj[key];
}
const s = Symbol();
const obj = {};
let prop;
// should work
prop = getProperty2(obj, 'first');
prop = getProperty3(obj, 'first');
// Should fail
prop = getProperty2(obj, s);
prop = getProperty3(obj, s);

View file

@ -0,0 +1,86 @@
=== tests/cases/compiler/extractInferenceImprovement.ts ===
// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065
function getProperty2<T, K extends keyof T>(obj: T, key: Extract<K, string>): T[K] {
>getProperty2 : Symbol(getProperty2, Decl(extractInferenceImprovement.ts, 0, 0))
>T : Symbol(T, Decl(extractInferenceImprovement.ts, 1, 22))
>K : Symbol(K, Decl(extractInferenceImprovement.ts, 1, 24))
>T : Symbol(T, Decl(extractInferenceImprovement.ts, 1, 22))
>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 1, 44))
>T : Symbol(T, Decl(extractInferenceImprovement.ts, 1, 22))
>key : Symbol(key, Decl(extractInferenceImprovement.ts, 1, 51))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>K : Symbol(K, Decl(extractInferenceImprovement.ts, 1, 24))
>T : Symbol(T, Decl(extractInferenceImprovement.ts, 1, 22))
>K : Symbol(K, Decl(extractInferenceImprovement.ts, 1, 24))
return obj[key];
>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 1, 44))
>key : Symbol(key, Decl(extractInferenceImprovement.ts, 1, 51))
}
function getProperty3<T, K extends Extract<keyof T, string>>(obj: T, key: K): T[K] {
>getProperty3 : Symbol(getProperty3, Decl(extractInferenceImprovement.ts, 3, 1))
>T : Symbol(T, Decl(extractInferenceImprovement.ts, 5, 22))
>K : Symbol(K, Decl(extractInferenceImprovement.ts, 5, 24))
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(extractInferenceImprovement.ts, 5, 22))
>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 5, 61))
>T : Symbol(T, Decl(extractInferenceImprovement.ts, 5, 22))
>key : Symbol(key, Decl(extractInferenceImprovement.ts, 5, 68))
>K : Symbol(K, Decl(extractInferenceImprovement.ts, 5, 24))
>T : Symbol(T, Decl(extractInferenceImprovement.ts, 5, 22))
>K : Symbol(K, Decl(extractInferenceImprovement.ts, 5, 24))
return obj[key];
>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 5, 61))
>key : Symbol(key, Decl(extractInferenceImprovement.ts, 5, 68))
}
const s = Symbol();
>s : Symbol(s, Decl(extractInferenceImprovement.ts, 9, 5))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
interface StrNum {
>StrNum : Symbol(StrNum, Decl(extractInferenceImprovement.ts, 9, 19))
first: string;
>first : Symbol(StrNum.first, Decl(extractInferenceImprovement.ts, 10, 18))
second: number;
>second : Symbol(StrNum.second, Decl(extractInferenceImprovement.ts, 11, 18))
[s]: string;
>[s] : Symbol(StrNum[s], Decl(extractInferenceImprovement.ts, 12, 19))
>s : Symbol(s, Decl(extractInferenceImprovement.ts, 9, 5))
}
const obj: StrNum = {} as any;
>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 15, 5))
>StrNum : Symbol(StrNum, Decl(extractInferenceImprovement.ts, 9, 19))
let prop: string;
>prop : Symbol(prop, Decl(extractInferenceImprovement.ts, 17, 3))
// should work
prop = getProperty2(obj, 'first');
>prop : Symbol(prop, Decl(extractInferenceImprovement.ts, 17, 3))
>getProperty2 : Symbol(getProperty2, Decl(extractInferenceImprovement.ts, 0, 0))
>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 15, 5))
prop = getProperty3(obj, 'first');
>prop : Symbol(prop, Decl(extractInferenceImprovement.ts, 17, 3))
>getProperty3 : Symbol(getProperty3, Decl(extractInferenceImprovement.ts, 3, 1))
>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 15, 5))
// Should fail
prop = getProperty2(obj, s);
>prop : Symbol(prop, Decl(extractInferenceImprovement.ts, 17, 3))
>getProperty2 : Symbol(getProperty2, Decl(extractInferenceImprovement.ts, 0, 0))
>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 15, 5))
>s : Symbol(s, Decl(extractInferenceImprovement.ts, 9, 5))
prop = getProperty3(obj, s);
>prop : Symbol(prop, Decl(extractInferenceImprovement.ts, 17, 3))
>getProperty3 : Symbol(getProperty3, Decl(extractInferenceImprovement.ts, 3, 1))
>obj : Symbol(obj, Decl(extractInferenceImprovement.ts, 15, 5))
>s : Symbol(s, Decl(extractInferenceImprovement.ts, 9, 5))

View file

@ -0,0 +1,82 @@
=== tests/cases/compiler/extractInferenceImprovement.ts ===
// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065
function getProperty2<T, K extends keyof T>(obj: T, key: Extract<K, string>): T[K] {
>getProperty2 : <T, K extends keyof T>(obj: T, key: Extract<K, string>) => T[K]
>obj : T
>key : Extract<K, string>
return obj[key];
>obj[key] : T[Extract<K, string>]
>obj : T
>key : Extract<K, string>
}
function getProperty3<T, K extends Extract<keyof T, string>>(obj: T, key: K): T[K] {
>getProperty3 : <T, K extends Extract<keyof T, string>>(obj: T, key: K) => T[K]
>obj : T
>key : K
return obj[key];
>obj[key] : T[K]
>obj : T
>key : K
}
const s = Symbol();
>s : unique symbol
>Symbol() : unique symbol
>Symbol : SymbolConstructor
interface StrNum {
first: string;
>first : string
second: number;
>second : number
[s]: string;
>[s] : string
>s : unique symbol
}
const obj: StrNum = {} as any;
>obj : StrNum
>{} as any : any
>{} : {}
let prop: string;
>prop : string
// should work
prop = getProperty2(obj, 'first');
>prop = getProperty2(obj, 'first') : string
>prop : string
>getProperty2(obj, 'first') : string
>getProperty2 : <T, K extends keyof T>(obj: T, key: Extract<K, string>) => T[K]
>obj : StrNum
>'first' : "first"
prop = getProperty3(obj, 'first');
>prop = getProperty3(obj, 'first') : string
>prop : string
>getProperty3(obj, 'first') : string
>getProperty3 : <T, K extends Extract<keyof T, string>>(obj: T, key: K) => T[K]
>obj : StrNum
>'first' : "first"
// Should fail
prop = getProperty2(obj, s);
>prop = getProperty2(obj, s) : any
>prop : string
>getProperty2(obj, s) : any
>getProperty2 : <T, K extends keyof T>(obj: T, key: Extract<K, string>) => T[K]
>obj : StrNum
>s : unique symbol
prop = getProperty3(obj, s);
>prop = getProperty3(obj, s) : any
>prop : string
>getProperty3(obj, s) : any
>getProperty3 : <T, K extends Extract<keyof T, string>>(obj: T, key: K) => T[K]
>obj : StrNum
>s : unique symbol

View file

@ -0,0 +1,29 @@
// @target: es6
// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065
function getProperty2<T, K extends keyof T>(obj: T, key: Extract<K, string>): T[K] {
return obj[key];
}
function getProperty3<T, K extends Extract<keyof T, string>>(obj: T, key: K): T[K] {
return obj[key];
}
const s = Symbol();
interface StrNum {
first: string;
second: number;
[s]: string;
}
const obj: StrNum = {} as any;
let prop: string;
// should work
prop = getProperty2(obj, 'first');
prop = getProperty3(obj, 'first');
// Should fail
prop = getProperty2(obj, s);
prop = getProperty3(obj, s);