-
Notifications
You must be signed in to change notification settings - Fork 12.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #32460 from microsoft/fix32434
Improve type inference for types like 'T | Promise<T>'
- Loading branch information
Showing
7 changed files
with
630 additions
and
325 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,61 @@ | ||
tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference.ts(9,15): error TS2345: Argument of type '2' is not assignable to parameter of type 'string | 1'. | ||
tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference.ts(13,24): error TS2345: Argument of type '1' is not assignable to parameter of type 'string'. | ||
tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference.ts(31,15): error TS2345: Argument of type '42' is not assignable to parameter of type 'never'. | ||
|
||
|
||
==== tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference.ts (1 errors) ==== | ||
// Verify that inferences made *to* a type parameter in a union type are secondary | ||
// to inferences made directly to that type parameter | ||
==== tests/cases/conformance/types/typeRelationships/typeInference/unionTypeInference.ts (2 errors) ==== | ||
declare const b: boolean; | ||
declare const s: string; | ||
declare const sn: string | number; | ||
|
||
function f<T>(x: T, y: string|T): T { | ||
return x; | ||
declare function f1<T>(x: T, y: string | T): T; | ||
|
||
const a1 = f1(1, 2); // 1 | 2 | ||
const a2 = f1(1, "hello"); // 1 | ||
const a3 = f1(1, sn); // number | ||
const a4 = f1(undefined, "abc"); // undefined | ||
const a5 = f1("foo", "bar"); // "foo" | ||
const a6 = f1(true, false); // boolean | ||
const a7 = f1("hello", 1); // Error | ||
~ | ||
!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'string'. | ||
|
||
declare function f2<T>(value: [string, T]): T; | ||
|
||
var b1 = f2(["string", true]); // boolean | ||
|
||
declare function f3<T>(x: string | false | T): T; | ||
|
||
const c1 = f3(5); // 5 | ||
const c2 = f3(sn); // number | ||
const c3 = f3(true); // true | ||
const c4 = f3(b); // true | ||
const c5 = f3("abc"); // never | ||
|
||
declare function f4<T>(x: string & T): T; | ||
|
||
const d1 = f4("abc"); | ||
const d2 = f4(s); | ||
const d3 = f4(42); // Error | ||
~~ | ||
!!! error TS2345: Argument of type '42' is not assignable to parameter of type 'never'. | ||
|
||
export interface Foo<T> { | ||
then<U>(f: (x: T) => U | Foo<U>, g: U): Foo<U>; | ||
} | ||
export interface Bar<T> { | ||
then<S>(f: (x: T) => S | Bar<S>, g: S): Bar<S>; | ||
} | ||
|
||
var a1: number; | ||
var a1 = f(1, 2); | ||
~ | ||
!!! error TS2345: Argument of type '2' is not assignable to parameter of type 'string | 1'. | ||
var a2: number; | ||
var a2 = f(1, "hello"); | ||
var a3: number; | ||
var a3 = f(1, a1 || "hello"); | ||
var a4: any; | ||
var a4 = f(undefined, "abc"); | ||
|
||
function g<T>(value: [string, T]): T { | ||
return value[1]; | ||
function qux(p1: Foo<void>, p2: Bar<void>) { | ||
p1 = p2; | ||
} | ||
|
||
var b1: boolean; | ||
var b1 = g(["string", true]); | ||
// Repros from #32434 | ||
|
||
function h<T>(x: string|boolean|T): T { | ||
return typeof x === "string" || typeof x === "boolean" ? undefined : x; | ||
} | ||
declare function foo<T>(x: T | Promise<T>): void; | ||
declare let x: false | Promise<true>; | ||
foo(x); | ||
|
||
var c1: number; | ||
var c1 = h(5); | ||
var c2: string; | ||
var c2 = h("abc"); | ||
declare function bar<T>(x: T, y: string | T): T; | ||
const y = bar(1, 2); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,78 @@ | ||
//// [unionTypeInference.ts] | ||
// Verify that inferences made *to* a type parameter in a union type are secondary | ||
// to inferences made directly to that type parameter | ||
declare const b: boolean; | ||
declare const s: string; | ||
declare const sn: string | number; | ||
|
||
function f<T>(x: T, y: string|T): T { | ||
return x; | ||
declare function f1<T>(x: T, y: string | T): T; | ||
|
||
const a1 = f1(1, 2); // 1 | 2 | ||
const a2 = f1(1, "hello"); // 1 | ||
const a3 = f1(1, sn); // number | ||
const a4 = f1(undefined, "abc"); // undefined | ||
const a5 = f1("foo", "bar"); // "foo" | ||
const a6 = f1(true, false); // boolean | ||
const a7 = f1("hello", 1); // Error | ||
|
||
declare function f2<T>(value: [string, T]): T; | ||
|
||
var b1 = f2(["string", true]); // boolean | ||
|
||
declare function f3<T>(x: string | false | T): T; | ||
|
||
const c1 = f3(5); // 5 | ||
const c2 = f3(sn); // number | ||
const c3 = f3(true); // true | ||
const c4 = f3(b); // true | ||
const c5 = f3("abc"); // never | ||
|
||
declare function f4<T>(x: string & T): T; | ||
|
||
const d1 = f4("abc"); | ||
const d2 = f4(s); | ||
const d3 = f4(42); // Error | ||
|
||
export interface Foo<T> { | ||
then<U>(f: (x: T) => U | Foo<U>, g: U): Foo<U>; | ||
} | ||
export interface Bar<T> { | ||
then<S>(f: (x: T) => S | Bar<S>, g: S): Bar<S>; | ||
} | ||
|
||
var a1: number; | ||
var a1 = f(1, 2); | ||
var a2: number; | ||
var a2 = f(1, "hello"); | ||
var a3: number; | ||
var a3 = f(1, a1 || "hello"); | ||
var a4: any; | ||
var a4 = f(undefined, "abc"); | ||
|
||
function g<T>(value: [string, T]): T { | ||
return value[1]; | ||
function qux(p1: Foo<void>, p2: Bar<void>) { | ||
p1 = p2; | ||
} | ||
|
||
var b1: boolean; | ||
var b1 = g(["string", true]); | ||
// Repros from #32434 | ||
|
||
function h<T>(x: string|boolean|T): T { | ||
return typeof x === "string" || typeof x === "boolean" ? undefined : x; | ||
} | ||
declare function foo<T>(x: T | Promise<T>): void; | ||
declare let x: false | Promise<true>; | ||
foo(x); | ||
|
||
var c1: number; | ||
var c1 = h(5); | ||
var c2: string; | ||
var c2 = h("abc"); | ||
declare function bar<T>(x: T, y: string | T): T; | ||
const y = bar(1, 2); | ||
|
||
|
||
//// [unionTypeInference.js] | ||
// Verify that inferences made *to* a type parameter in a union type are secondary | ||
// to inferences made directly to that type parameter | ||
function f(x, y) { | ||
return x; | ||
} | ||
var a1; | ||
var a1 = f(1, 2); | ||
var a2; | ||
var a2 = f(1, "hello"); | ||
var a3; | ||
var a3 = f(1, a1 || "hello"); | ||
var a4; | ||
var a4 = f(undefined, "abc"); | ||
function g(value) { | ||
return value[1]; | ||
} | ||
var b1; | ||
var b1 = g(["string", true]); | ||
function h(x) { | ||
return typeof x === "string" || typeof x === "boolean" ? undefined : x; | ||
"use strict"; | ||
exports.__esModule = true; | ||
var a1 = f1(1, 2); // 1 | 2 | ||
var a2 = f1(1, "hello"); // 1 | ||
var a3 = f1(1, sn); // number | ||
var a4 = f1(undefined, "abc"); // undefined | ||
var a5 = f1("foo", "bar"); // "foo" | ||
var a6 = f1(true, false); // boolean | ||
var a7 = f1("hello", 1); // Error | ||
var b1 = f2(["string", true]); // boolean | ||
var c1 = f3(5); // 5 | ||
var c2 = f3(sn); // number | ||
var c3 = f3(true); // true | ||
var c4 = f3(b); // true | ||
var c5 = f3("abc"); // never | ||
var d1 = f4("abc"); | ||
var d2 = f4(s); | ||
var d3 = f4(42); // Error | ||
function qux(p1, p2) { | ||
p1 = p2; | ||
} | ||
var c1; | ||
var c1 = h(5); | ||
var c2; | ||
var c2 = h("abc"); | ||
foo(x); | ||
var y = bar(1, 2); |
Oops, something went wrong.