Allow drawing inferences to conditional type branches (#27012)
* Allow drawing inferences to conditional type branches * Fix lint
This commit is contained in:
parent
c3b4f72498
commit
a55c0b7df9
|
@ -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) {
|
||||
|
|
|
@ -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"'.
|
||||
|
48
tests/baselines/reference/extractInferenceImprovement.js
Normal file
48
tests/baselines/reference/extractInferenceImprovement.js
Normal 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);
|
|
@ -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))
|
||||
|
82
tests/baselines/reference/extractInferenceImprovement.types
Normal file
82
tests/baselines/reference/extractInferenceImprovement.types
Normal 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
|
||||
|
29
tests/cases/compiler/extractInferenceImprovement.ts
Normal file
29
tests/cases/compiler/extractInferenceImprovement.ts
Normal 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);
|
Loading…
Reference in a new issue