diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 31144ec5b5..6d400b99e8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13508,6 +13508,9 @@ namespace ts { inferFromTypes(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target)); inferFromTypes(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target)); } + else if (target.flags & TypeFlags.Conditional) { + inferFromTypes(source, getUnionType([getTrueTypeFromConditionalType(target), getFalseTypeFromConditionalType(target)])); + } else if (target.flags & TypeFlags.UnionOrIntersection) { const targetTypes = (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) { diff --git a/tests/baselines/reference/extractInferenceImprovement.errors.txt b/tests/baselines/reference/extractInferenceImprovement.errors.txt new file mode 100644 index 0000000000..b3582f6b02 --- /dev/null +++ b/tests/baselines/reference/extractInferenceImprovement.errors.txt @@ -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(obj: T, key: Extract): T[K] { + return obj[key]; + } + + function getProperty3>(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"'. + \ No newline at end of file diff --git a/tests/baselines/reference/extractInferenceImprovement.js b/tests/baselines/reference/extractInferenceImprovement.js new file mode 100644 index 0000000000..c377d3141d --- /dev/null +++ b/tests/baselines/reference/extractInferenceImprovement.js @@ -0,0 +1,48 @@ +//// [extractInferenceImprovement.ts] +// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065 +function getProperty2(obj: T, key: Extract): T[K] { + return obj[key]; +} + +function getProperty3>(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); diff --git a/tests/baselines/reference/extractInferenceImprovement.symbols b/tests/baselines/reference/extractInferenceImprovement.symbols new file mode 100644 index 0000000000..39977a99e7 --- /dev/null +++ b/tests/baselines/reference/extractInferenceImprovement.symbols @@ -0,0 +1,86 @@ +=== tests/cases/compiler/extractInferenceImprovement.ts === +// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065 +function getProperty2(obj: T, key: Extract): 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>(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)) + diff --git a/tests/baselines/reference/extractInferenceImprovement.types b/tests/baselines/reference/extractInferenceImprovement.types new file mode 100644 index 0000000000..0e18dc30ee --- /dev/null +++ b/tests/baselines/reference/extractInferenceImprovement.types @@ -0,0 +1,82 @@ +=== tests/cases/compiler/extractInferenceImprovement.ts === +// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065 +function getProperty2(obj: T, key: Extract): T[K] { +>getProperty2 : (obj: T, key: Extract) => T[K] +>obj : T +>key : Extract + + return obj[key]; +>obj[key] : T[Extract] +>obj : T +>key : Extract +} + +function getProperty3>(obj: T, key: K): T[K] { +>getProperty3 : >(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 : (obj: T, key: Extract) => T[K] +>obj : StrNum +>'first' : "first" + +prop = getProperty3(obj, 'first'); +>prop = getProperty3(obj, 'first') : string +>prop : string +>getProperty3(obj, 'first') : string +>getProperty3 : >(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 : (obj: T, key: Extract) => T[K] +>obj : StrNum +>s : unique symbol + +prop = getProperty3(obj, s); +>prop = getProperty3(obj, s) : any +>prop : string +>getProperty3(obj, s) : any +>getProperty3 : >(obj: T, key: K) => T[K] +>obj : StrNum +>s : unique symbol + diff --git a/tests/cases/compiler/extractInferenceImprovement.ts b/tests/cases/compiler/extractInferenceImprovement.ts new file mode 100644 index 0000000000..f70e6c07e8 --- /dev/null +++ b/tests/cases/compiler/extractInferenceImprovement.ts @@ -0,0 +1,29 @@ +// @target: es6 +// repro mostly from https://github.com/Microsoft/TypeScript/issues/25065 +function getProperty2(obj: T, key: Extract): T[K] { + return obj[key]; +} + +function getProperty3>(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);